home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 380.lha / post_v1.1 / source / post.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-06-10  |  70.6 KB  |  2,363 lines

  1. /* PostScript interpreter file "post.c" - the main program (Amiga)
  2.  * (C) Adrian Aylward 1989, 1990
  3.  *
  4.  * This file contains the code to parse the command line arguments, the
  5.  * WorkBench and intuition interface, and the printer screen or IFF file]
  6.  * output routines.  It is therfore heavily Amiga dependent.  It calls the
  7.  * interpreter library for all the PostScript stuff.
  8.  *
  9.  * There are also various Lattice dependencies: the startup code in _main,
  10.  * the menu task, the flush and copy functions, and the floating point trap
  11.  * and break handling.
  12.  */
  13.  
  14. # include <arpbase.h>
  15. # include <dos.h>
  16. # include <devices/printer.h>
  17. # include <devices/prtbase.h>
  18. # include <exec/exec.h>
  19. # include <exec/execbase.h>
  20. # include <exec/tasks.h>
  21. # include <graphics/gfxbase.h>
  22. # include <graphics/text.h>
  23. # include <intuition/intuition.h>
  24. # include <libraries/dosextens.h>
  25. # include <workbench/icon.h>
  26. # include <workbench/startup.h>
  27. # include <workbench/workbench.h>
  28. # include <proto/diskfont.h>
  29. # include <proto/dos.h>
  30. # include <proto/exec.h>
  31. # include <proto/graphics.h>
  32. # include <proto/icon.h>
  33. # include <proto/intuition.h>
  34. # include <stdio.h>
  35. # include <fcntl.h>
  36. # include <ios1.h>
  37.  
  38. # include "postlib.h"
  39.  
  40. /* Assembler routines */
  41.  
  42. extern void insertbreak(void);
  43. extern void deletebreak(void);
  44. extern void insertftrap(void);
  45. extern void deleteftrap(void);
  46.  
  47. /* Routines defined and referenced only within this module */
  48.  
  49. extern void errmsg(char *string);
  50. extern void tidyup(void);
  51. extern void setprinter(void);
  52. extern void setprintden(void);
  53. extern void setreqgadgets(void);
  54. extern void getreqgadgets(void);
  55. extern void enablegadg(struct Gadget *gadget, int enable);
  56. extern void setgadgbool(struct Gadget *gadget, int value);
  57. extern int  getgadgbool(struct Gadget *gadget);
  58. extern void setgadgint(struct Gadget *gadget, int value);
  59. extern int  getgadgint(struct Gadget *gadget);
  60. extern int  strtoint(char **sp, int *ip);
  61. extern void sendmenu(int action);
  62. extern void __saveds menuproc(void);
  63. # ifndef STATICLINK
  64. extern void __saveds __asm flushpage(register __d0 int y1,
  65.                                      register __d1 int y2);
  66. extern void __saveds __asm copypage(register __d0 int num);
  67. # endif
  68. extern void printpage(void);
  69. extern void iffpage(void);
  70. extern int  igcd(int n, int m);
  71.  
  72. /* Message structure */
  73.  
  74. struct PSmessage
  75. {   struct Message ExecMessage;
  76.     long class;            /* Always zero */
  77.     short action;          /* Action - from Post to handler */
  78.     short command;         /* Command - from handler to Post */
  79.     struct BitMap *bitmap; /* The bitmap */
  80.     short y1, y2;          /* Min and max+1 y values to flush */
  81.     short result;          /* Result  (return code) */
  82.     short length;          /* Length of string */
  83.     char *string;          /* String */
  84.     long window;           /* Always zero */
  85.     short errnum;          /* Last error number */
  86.     short zero;            /* Reserved, presently always zero */
  87. };
  88.  
  89. /* Actions */
  90.  
  91. # define PSACTOPEN    1 /* Open */
  92. # define PSACTCLOSE   2 /* Close */
  93. # define PSACTFLUSH   3 /* Flush out the bitmap */
  94. # define PSACTPAUSE   4 /* Pause at the end of a page */
  95. # define PSACTCOMMAND 5 /* Get a command */
  96. # define PSACTEXIT    6 /* Exit */
  97.  
  98. /* Commands */
  99.  
  100. # define PSCOMQUIT    1 /* Quit */
  101. # define PSCOMRESTART 2 /* Restart */
  102. # define PSCOMFILEF   3 /* Load Font */
  103. # define PSCOMFILEL   4 /* Load File */
  104. # define PSCOMFILER   5 /* Run File */
  105. # define PSCOMINTER   6 /* Interactive */
  106.  
  107. /* Lattice startup */
  108.  
  109. extern struct WBStartup *WBenchMsg;
  110.  
  111. extern struct UFB _ufbs[];
  112.  
  113. /* External data (initialised to zero) */
  114.  
  115. int retcode, errcode, ioerror;
  116. int fatalerror, restarterror, requested;
  117.  
  118. int arec;
  119.  
  120. BPTR errfh, confh;
  121.  
  122. # ifndef STATICLINK
  123. struct library *PSbase;
  124. # endif
  125. struct PSparm parm;
  126. struct PSmessage menumsg;
  127.  
  128. struct ArpBase *ArpBase;
  129. struct FileRequester *filereq, *filereq1, *filereq2;
  130.  
  131. struct Process *process;
  132. struct MsgPort *mainport, *menuport;
  133. struct Task *menutask;
  134. struct Screen *screen;
  135. struct Window *syswindow, *reqwindow, *errwindow, *bitwindow, *intwindow;
  136. struct BitMap bitmap;
  137. struct ColorMap colormap;
  138. struct TextFont *textfont;
  139.  
  140. int propen, prden;
  141. struct IODRPReq prreq;
  142. struct PrinterData *prdata;
  143. struct PrinterExtendedData *prextdata;
  144. struct Preferences *prprefs;
  145. struct RastPort prrast;
  146. struct MsgPort *prport;
  147. ULONG prsig;
  148. UBYTE prstatus[2];
  149.  
  150. int breakset, ftrapset;
  151.  
  152. int winxbase, winybase, winxsize, winysize, winxpos, winypos;
  153.  
  154. /* Colour tables.  The default color map type is a vector or UWORD RGB
  155.  * values.  The colours are inverted as we set a bit in the bitmap whenever
  156.  * we want to place a drop of (black or cyan/magenta/yellow) ink */
  157.  
  158. static UWORD bcolors[2] =  /* Black and white */
  159. {   0xfff, 0x000                /* White   black */
  160. };
  161.  
  162. static UWORD ccolors[16] = /* Colour (RGB or CMYK) */
  163. {   0xfff, 0x0ff, 0xf0f, 0x00f, /* White   cyan    magenta blue */
  164.     0xff0, 0x0f0, 0xf00, 0x000, /* Yellow  green   red     black */
  165.     0x000, 0x000, 0x000, 0x000, /* Black */
  166.     0x000, 0x000, 0x000, 0x000  /* Black */
  167. };
  168.  
  169. char titlewait[]    = POSTVER " Copyright Adrian Aylward 1989, 1990";
  170. char titlestart[]   = POSTVER " Running startup file(s)";
  171. char titlerunning[] = POSTVER " Running";
  172. char titleinter[]   = POSTVER " Interactive";
  173. char titlepaused[]  = POSTVER " Paused";
  174.  
  175. char hailfilef[]    = POSTVER " Select font to load";
  176. char hailfilen[]    = POSTVER " Select file to load";
  177. char hailfiles[]    = POSTVER " Select file to run";
  178.  
  179. /* The default font and screen */
  180.  
  181. struct TextAttr topaz11 =       /* Font is Topaz 11 */
  182. {   "topaz.font", 11, FS_NORMAL, FPF_DISKFONT };
  183.  
  184. struct NewScreen newscreen =    /* Screen */
  185. {   0, 0, 640, 512, 1, 0, 15, LACE|HIRES, CUSTOMSCREEN, &topaz11,
  186.     (UBYTE *) &titlewait, NULL, NULL
  187. };
  188.  
  189. /* Stuff for the options requestor */
  190.  
  191. # define GADGOK    1  /* Gadget id's */
  192. # define GADGCAN   2
  193. # define GADGPRI   3
  194. # define GADGBW    4
  195. # define GADGC3    5
  196. # define GADGC4    6
  197. # define GADGPD1   7
  198. # define GADGPD2   8
  199. # define GADGPD3   9
  200. # define GADGPD4  10
  201. # define GADGPD5  11
  202. # define GADGPD6  12
  203. # define GADGPD7  13
  204. # define GADGRST  14  /* Dummy gadget to restart after error */
  205.  
  206. char undobuff[80];
  207.  
  208. SHORT bordervec1[] =
  209. {   0, 0, 67, 0, 67, 14, 0, 14, 0, 1 };
  210. struct Border border1 =
  211. {   -2, -2, 15, 0, JAM1, 5, bordervec1, NULL };
  212.  
  213. UBYTE mhgadgbuff[8];
  214. struct StringInfo mhgadginfo =
  215. {   mhgadgbuff, (UBYTE *)undobuff, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, NULL };
  216. struct Gadget mhgadg =
  217. {   NULL,    500, 226, 64, 13, 0, STRINGRIGHT|LONGINT, STRGADGET,
  218.     (APTR)&border1, NULL, NULL, 0, (APTR)&mhgadginfo, 0, NULL };
  219.  
  220. UBYTE mlgadgbuff[8];
  221. struct StringInfo mlgadginfo =
  222. {   mlgadgbuff, (UBYTE *)undobuff, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, NULL };
  223. struct Gadget mlgadg =
  224. {   &mhgadg, 500, 212, 64, 13, 0, STRINGRIGHT|LONGINT, STRGADGET,
  225.     (APTR)&border1, NULL, NULL, 0, (APTR)&mlgadginfo, 0, NULL };
  226.  
  227. UBYTE mfgadgbuff[8];
  228. struct StringInfo mfgadginfo =
  229. {   mfgadgbuff, (UBYTE *)undobuff, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, NULL };
  230. struct Gadget mfgadg =
  231. {   &mlgadg, 500, 198, 64, 13, 0, STRINGRIGHT|LONGINT, STRGADGET,
  232.     (APTR)&border1, NULL, NULL, 0, (APTR)&mfgadginfo, 0, NULL };
  233.  
  234. UBYTE mvgadgbuff[8];
  235. struct StringInfo mvgadginfo =
  236. {   mvgadgbuff, (UBYTE *)undobuff, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, NULL };
  237. struct Gadget mvgadg =
  238. {   &mfgadg, 500, 184, 64, 13, 0, STRINGRIGHT|LONGINT, STRGADGET,
  239.     (APTR)&border1, NULL, NULL, 0, (APTR)&mvgadginfo, 0, NULL };
  240.  
  241. SHORT bordervec2[] =
  242. {   0, 0, 43, 0, 43, 14, 0, 14, 0, 1 };
  243. struct Border border2 =
  244. {   -2, -2, 15, 0, JAM1, 5, bordervec2, NULL };
  245.  
  246.  
  247. UBYTE ydgadgbuff[5];
  248. struct StringInfo ydgadginfo =
  249. {   ydgadgbuff, (UBYTE *)undobuff, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, NULL };
  250. struct Gadget ydgadg =
  251. {   &mvgadg, 388, 198, 40, 13, 0, STRINGRIGHT|LONGINT, STRGADGET,
  252.     (APTR)&border2, NULL, NULL, 0, (APTR)&ydgadginfo, 0, NULL };
  253.  
  254. UBYTE xdgadgbuff[5];
  255. struct StringInfo xdgadginfo =
  256. {   xdgadgbuff, (UBYTE *)undobuff, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, NULL };
  257. struct Gadget xdgadg =
  258. {   &ydgadg, 345, 198, 40, 13, 0, STRINGRIGHT|LONGINT, STRGADGET,
  259.     (APTR)&border2, NULL, NULL, 0, (APTR)&xdgadginfo, 0, NULL };
  260.  
  261. UBYTE ygadgbuff[5];
  262. struct StringInfo ygadginfo =
  263. {   ygadgbuff, (UBYTE *)undobuff, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, NULL };
  264. struct Gadget ygadg =
  265. {   &xdgadg, 388, 184, 40, 13, 0, STRINGRIGHT|LONGINT, STRGADGET,
  266.     (APTR)&border2, NULL, NULL, 0, (APTR)&ygadginfo, 0, NULL };
  267.  
  268. UBYTE xgadgbuff[5];
  269. struct StringInfo xgadginfo =
  270. {   xgadgbuff, (UBYTE *)undobuff, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, NULL };
  271. struct Gadget xgadg =
  272. {   &ygadg, 345, 184, 40, 13, 0, STRINGRIGHT|LONGINT, STRGADGET,
  273.     (APTR)&border2, NULL, NULL, 0, (APTR)&xgadginfo, 0, NULL };
  274.  
  275. short __chip idata1[] =
  276. {   0xfffe, 0x8002, 0x8002, 0x8002, 0x8002, 0x8002, 0x8002, 0x8002,
  277.     0x8002, 0x8002, 0x8002, 0x8002, 0x8002, 0x8002, 0xfffe,
  278.     0xfffe, 0x8002, 0x8002, 0x8002, 0x8002, 0x8002, 0x8002, 0x8002,
  279.     0x8002, 0x8002, 0x8002, 0x8002, 0x8002, 0x8002, 0xfffe,
  280.     0xfffe, 0x8002, 0x8002, 0x8002, 0x8002, 0x8002, 0x8002, 0x8002,
  281.     0x8002, 0x8002, 0x8002, 0x8002, 0x8002, 0x8002, 0xfffe,
  282.     0xfffe, 0x8002, 0x8002, 0x8002, 0x8002, 0x8002, 0x8002, 0x8002,
  283.     0x8002, 0x8002, 0x8002, 0x8002, 0x8002, 0x8002, 0xfffe };
  284. struct Image image1 =
  285. {   -2, -2, 15, 15, 4, &idata1[0], 15, 0, NULL };
  286.  
  287. struct IntuiText itext29 =
  288. {   15, 0, JAM2, 1, 1, NULL, "7", NULL };
  289. struct IntuiText itext28 =
  290. {   15, 0, JAM2, 1, 1, NULL, "6", NULL };
  291. struct IntuiText itext27 =
  292. {   15, 0, JAM2, 1, 1, NULL, "5", NULL };
  293. struct IntuiText itext26 =
  294. {   15, 0, JAM2, 1, 1, NULL, "4", NULL };
  295. struct IntuiText itext25 =
  296. {   15, 0, JAM2, 1, 1, NULL, "3", NULL };
  297. struct IntuiText itext24 =
  298. {   15, 0, JAM2, 1, 1, NULL, "2", NULL };
  299. struct IntuiText itext23 =
  300. {   15, 0, JAM2, 1, 1, NULL, "1", NULL };
  301.  
  302. struct Gadget pd7gadg =
  303. {   &xgadg,   526, 128, 11, 11, GADGIMAGE, RELVERIFY, BOOLGADGET,
  304.     (APTR)&image1, NULL, &itext29, 0, NULL, GADGPD7, NULL };
  305. struct Gadget pd6gadg =
  306. {   &pd7gadg, 512, 128, 11, 11, GADGIMAGE, RELVERIFY, BOOLGADGET,
  307.     (APTR)&image1, NULL, &itext28, 0, NULL, GADGPD6, NULL };
  308. struct Gadget pd5gadg =
  309. {   &pd6gadg, 498, 128, 11, 11, GADGIMAGE, RELVERIFY, BOOLGADGET,
  310.     (APTR)&image1, NULL, &itext27, 0, NULL, GADGPD5, NULL };
  311. struct Gadget pd4gadg =
  312. {   &pd5gadg, 484, 128, 11, 11, GADGIMAGE, RELVERIFY, BOOLGADGET,
  313.     (APTR)&image1, NULL, &itext26, 0, NULL, GADGPD4, NULL };
  314. struct Gadget pd3gadg =
  315. {   &pd4gadg, 470, 128, 11, 11, GADGIMAGE, RELVERIFY, BOOLGADGET,
  316.     (APTR)&image1, NULL, &itext25, 0, NULL, GADGPD3, NULL };
  317. struct Gadget pd2gadg =
  318. {   &pd3gadg, 456, 128, 11, 11, GADGIMAGE, RELVERIFY, BOOLGADGET,
  319.     (APTR)&image1, NULL, &itext24, 0, NULL, GADGPD2, NULL };
  320. struct Gadget pd1gadg =
  321. {   &pd2gadg, 442, 128, 11, 11, GADGIMAGE, RELVERIFY, BOOLGADGET,
  322.     (APTR)&image1, NULL, &itext23, 0, NULL, GADGPD1, NULL };
  323.  
  324. struct Gadget cwbgadg =
  325. {   &pd1gadg, 417, 226, 11, 11, GADGIMAGE, TOGGLESELECT, BOOLGADGET,
  326.     (APTR)&image1, NULL, NULL, 0, NULL, 0, NULL };
  327.  
  328. struct Gadget c4gadg =
  329. {   &cwbgadg, 553, 86, 11, 11, GADGIMAGE, RELVERIFY, BOOLGADGET,
  330.     (APTR)&image1, NULL, NULL, 0, NULL, GADGC4, NULL };
  331. struct Gadget c3gadg =
  332. {   &c4gadg, 553, 72, 11, 11, GADGIMAGE, RELVERIFY, BOOLGADGET,
  333.     (APTR)&image1, NULL, NULL, 0, NULL, GADGC3, NULL };
  334. struct Gadget bwgadg =
  335. {   &c3gadg, 553, 58, 11, 11, GADGIMAGE, RELVERIFY, BOOLGADGET,
  336.     (APTR)&image1, NULL, NULL, 0, NULL, GADGBW, NULL };
  337.  
  338. struct Gadget iffgadg =
  339. {   &bwgadg, 382, 86, 11, 11, GADGIMAGE, TOGGLESELECT, BOOLGADGET,
  340.     (APTR)&image1, NULL, NULL, 0, NULL, 0, NULL };
  341. struct Gadget scrgadg =
  342. {   &iffgadg, 382, 72, 11, 11, GADGIMAGE, TOGGLESELECT, BOOLGADGET,
  343.     (APTR)&image1, NULL, NULL, 0, NULL, 0, NULL };
  344. struct Gadget prigadg =
  345. {   &scrgadg, 382, 58, 11, 11, GADGIMAGE, TOGGLESELECT|RELVERIFY, BOOLGADGET,
  346.     (APTR)&image1, NULL, NULL, 0, NULL, GADGPRI, NULL };
  347.  
  348. SHORT bordervec3[] =
  349. {   0, 0, 101, 0, 101, 33, 0, 33, 0, 1 };
  350. struct Border border3 =
  351. {   -1, -1, 15, 0, JAM1, 5, bordervec3, NULL };
  352.  
  353. struct IntuiText itext1 =
  354. {   15, 0, JAM1, 26, 11, NULL, "CANCEL", NULL };
  355. struct Gadget cangadg =
  356. {   &prigadg, 174, 219, 100, 32, 0, RELVERIFY, BOOLGADGET,
  357.     (APTR)&border3, NULL, &itext1, 0, NULL, GADGCAN, NULL };
  358.  
  359. struct IntuiText itext2 =
  360. {   15, 0, JAM1, 43, 11, NULL, "OK", NULL };
  361. struct Gadget okgadg =
  362. {   &cangadg, 24, 219, 100, 32, 0, RELVERIFY, BOOLGADGET,
  363.     (APTR)&border3, NULL, &itext2, 0, NULL, GADGOK, NULL };
  364.  
  365. SHORT bordervec4[] =
  366. {   0, 0, 251, 0, 251, 14, 0, 14, 0, 1 };
  367. struct Border border4 =
  368. {   -2, -2, 15, 0, JAM1, 5, bordervec4, NULL };
  369.  
  370. UBYTE ifngadgbuff[80];
  371. struct StringInfo ifngadginfo =
  372. {   ifngadgbuff, (UBYTE *)undobuff, 0, 80, 0, 0, 0, 0, 0, 0, 0, 0, NULL };
  373. struct Gadget ifngadg =
  374. {   &okgadg, 25, 170, 250, 13, 0, 0, STRGADGET,
  375.     (APTR)&border4, NULL, NULL, 0, (APTR)&ifngadginfo, 0, NULL };
  376.  
  377. UBYTE if4gadgbuff[80];
  378. struct StringInfo if4gadginfo =
  379. {   if4gadgbuff, (UBYTE *)undobuff, 0, 80, 0, 0, 0, 0, 0, 0, 0, 0, NULL };
  380. struct Gadget if4gadg =
  381. {   &ifngadg, 25, 114, 250, 13, 0, 0, STRGADGET,
  382.     (APTR)&border4, NULL, NULL, 0, (APTR)&if4gadginfo, 0, NULL };
  383.  
  384. UBYTE if3gadgbuff[80];
  385. struct StringInfo if3gadginfo =
  386. {   if3gadgbuff, (UBYTE *)undobuff, 0, 80, 0, 0, 0, 0, 0, 0, 0, 0, NULL };
  387. struct Gadget if3gadg =
  388. {   &if4gadg, 25, 100, 250, 13, 0, 0, STRGADGET,
  389.     (APTR)&border4, NULL, NULL, 0, (APTR)&if3gadginfo, 0, NULL };
  390.  
  391. UBYTE if2gadgbuff[80];
  392. struct StringInfo if2gadginfo =
  393. {   if2gadgbuff, (UBYTE *)undobuff, 0, 80, 0, 0, 0, 0, 0, 0, 0, 0, NULL };
  394. struct Gadget if2gadg =
  395. {   &if3gadg, 25, 86, 250, 13, 0, 0, STRGADGET,
  396.     (APTR)&border4, NULL, NULL, 0, (APTR)&if2gadginfo, 0, NULL };
  397.  
  398. UBYTE if1gadgbuff[80];
  399. struct StringInfo if1gadginfo =
  400. {   if1gadgbuff, (UBYTE *)undobuff, 0, 80, 0, 0, 0, 0, 0, 0, 0, 0, NULL };
  401. struct Gadget if1gadg =
  402. {   &if2gadg, 25, 72, 250, 13, 0, 0, STRGADGET,
  403.     (APTR)&border4, NULL, NULL, 0, (APTR)&if1gadginfo, 0, NULL };
  404.  
  405. UBYTE if0gadgbuff[80];
  406. struct StringInfo if0gadginfo =
  407. {   if0gadgbuff, (UBYTE *)undobuff, 0, 80, 0, 0, 0, 0, 0, 0, 0, 0, NULL };
  408. struct Gadget if0gadg =
  409. {   &if1gadg, 25, 58, 250, 13, 0, 0, STRGADGET,
  410.     (APTR)&border4, NULL, NULL, 0, (APTR)&if0gadginfo, 0, NULL };
  411.  
  412. struct IntuiText itext22 =
  413. {   15, 0, JAM1, 300, 226, NULL, "Close WBench", NULL };
  414. struct IntuiText itext21 =
  415. {   15, 0, JAM1, 448, 226, NULL, "Htone", &itext22 };
  416. struct IntuiText itext20 =
  417. {   15, 0, JAM1, 448, 198, NULL, "Fonts", &itext21 };
  418. struct IntuiText itext19 =
  419. {   15, 0, JAM1, 448, 212, NULL, "Paths", &itext20 };
  420. struct IntuiText itext18 =
  421. {   15, 0, JAM1, 448, 184, NULL, "VM", &itext19 };
  422. struct IntuiText itext17 =
  423. {   15, 0, JAM1, 448, 156, NULL, "Memory", &itext18 };
  424. struct IntuiText itext16 =
  425. {   15, 0, JAM1, 300, 198, NULL, "Dpi.", &itext17 };
  426. struct IntuiText itext15 =
  427. {   15, 0, JAM1, 300, 184, NULL, "X, Y", &itext16 };
  428. struct IntuiText itext14 =
  429. {   15, 0, JAM1, 300, 156, NULL, "Page size", &itext15 };
  430. struct IntuiText itext13 =
  431. {   15, 0, JAM1, 300, 128, NULL, "Printer density", &itext14 };
  432. struct IntuiText itext12 =
  433. {   15, 0, JAM1, 416, 86, NULL, "4 Colour (CMYK)", &itext13 };
  434. struct IntuiText itext11 =
  435. {   15, 0, JAM1, 416, 72, NULL, "3 Colour (RGB)", &itext12 };
  436. struct IntuiText itext10 =
  437. {   15, 0, JAM1, 416, 58, NULL, "Black and white", &itext11 };
  438. struct IntuiText itext9 =
  439. {   15, 0, JAM1, 300, 86, NULL, "IFF file", &itext10 };
  440. struct IntuiText itext8 =
  441. {   15, 0, JAM1, 300, 72, NULL, "Screen", &itext9 };
  442. struct IntuiText itext7 =
  443. {   15, 0, JAM1, 300, 58, NULL, "Printer", &itext8 };
  444. struct IntuiText itext6 =
  445. {   15, 0, JAM1, 416, 30, NULL, "Colours", &itext7 };
  446. struct IntuiText itext5 =
  447. {   15, 0, JAM1, 300, 30, NULL, "Output", &itext6 };
  448. struct IntuiText itext4 =
  449. {   15, 0, JAM1, 25, 156, NULL, "IFF file name (pattern)", &itext5 };
  450. struct IntuiText itext3 =
  451. {   15, 0, JAM1, 25, 30, NULL, "Startup file name(s)", &itext4 };
  452.  
  453. struct NewWindow newreqwindow =
  454. {   25, 60, 590, 260, 0, 15,
  455.     GADGETUP|GADGETDOWN, ACTIVATE|SMART_REFRESH|NOCAREREFRESH,
  456.     &if0gadg, NULL, POSTVER, NULL, NULL, 0, 0, 0, 0, CUSTOMSCREEN
  457. };
  458.  
  459. struct NewWindow newerrwindow =
  460. {   0, 100, 640, 100, 0, 15,
  461.     0, SIMPLE_REFRESH|NOCAREREFRESH|BACKDROP|BORDERLESS,
  462.     NULL, NULL, NULL, NULL, NULL, 0, 0, 0, 0, CUSTOMSCREEN
  463. };
  464.  
  465. /* Stuff for the windows */
  466.  
  467. struct PropInfo hscrollinfo =   /* Horizontal scroll proportional gadget */
  468. {   AUTOKNOB|FREEHORIZ, -1, -1, -1, -1 };
  469. struct Image hscrollimage;
  470. struct Gadget hscrollgadg =
  471. {   NULL, 0, -8, -14, 9,
  472.     GRELBOTTOM|GRELWIDTH, BOTTOMBORDER|RELVERIFY, PROPGADGET,
  473.     (APTR)&hscrollimage, NULL, NULL, 0, (APTR)&hscrollinfo, 0, NULL
  474. };
  475.  
  476. struct PropInfo vscrollinfo =   /* Vertical scroll proportional gadget */
  477. {   AUTOKNOB|FREEVERT, -1, -1, -1, -1 };
  478. struct Image vscrollimage;
  479. struct Gadget vscrollgadg =
  480. {   &hscrollgadg, -15, 0, 16, -8,
  481.     GRELRIGHT|GRELHEIGHT, RIGHTBORDER|RELVERIFY, PROPGADGET,
  482.     (APTR)&vscrollimage, NULL, NULL, 0, (APTR)&vscrollinfo, 0, NULL
  483. };
  484.  
  485. struct NewWindow newbitwindow = /* Bitmap window.  (Borders (4,2,18,10)) */
  486. {   0, 49, 640, 463, -1, -1,
  487.     0, SIMPLE_REFRESH,
  488.     &vscrollgadg, NULL, NULL, NULL, NULL,
  489.     0, 100, 0, 0, CUSTOMSCREEN
  490. };
  491.  
  492. struct NewWindow newintwindow = /* Interactive window */
  493. {   0, 12, 640, 37, -1, -1,
  494.     0, SIZEBRIGHT|WINDOWSIZING|SMART_REFRESH|ACTIVATE,
  495.     NULL, NULL, NULL, NULL, NULL,
  496.     0, 0, 0, 400, CUSTOMSCREEN
  497. };
  498.  
  499. struct IntuiText men2item2text = /* Menu strip */
  500. {   7, 0, COMPLEMENT, 0, 0, NULL, "Interrupt", NULL };
  501. struct MenuItem men2item2 =
  502. {   NULL, 0, 40, 200, 11, ITEMTEXT|COMMSEQ|ITEMENABLED|HIGHCOMP,
  503.     0, (APTR)&men2item2text, NULL, 'I', NULL, MENUNULL
  504. };
  505.  
  506. struct IntuiText men2item1text =
  507. {   7, 0, COMPLEMENT, 0, 0, NULL, "Continue after pause", NULL };
  508. struct MenuItem men2item1 =
  509. {   &men2item2, 0, 20, 200, 11, ITEMTEXT|COMMSEQ|HIGHCOMP,
  510.     0, (APTR)&men2item1text, NULL, 'C', NULL, MENUNULL
  511. };
  512.  
  513. struct IntuiText men2item0text =
  514. {   7, 0, COMPLEMENT, 19, 0, NULL, "Pause every page", NULL };
  515. struct MenuItem men2item0 =
  516. {   &men2item1, 0, 0, 200,11,
  517.     CHECKIT|ITEMTEXT|COMMSEQ|ITEMENABLED|HIGHCOMP|CHECKED,
  518.     0, (APTR)&men2item0text, NULL, 'P', NULL, MENUNULL
  519. };
  520.  
  521. struct Menu menu2 =
  522. {   NULL, 160, 0, 80, 0, MENUENABLED, "Control", &men2item0 };
  523.  
  524. struct IntuiText men1item3text =
  525. {   7, 0, COMPLEMENT, 0, 0, NULL, "Interactive", NULL };
  526. struct MenuItem men1item3 =
  527. {   NULL, 0, 60, 128, 11, ITEMTEXT|COMMSEQ|ITEMENABLED|HIGHCOMP,
  528.     0, (APTR)&men1item3text, NULL, 'W', NULL, MENUNULL
  529. };
  530.  
  531. struct IntuiText men1item2text =
  532. {   7, 0, COMPLEMENT, 0, 0, NULL, "Run file", NULL };
  533. struct MenuItem men1item2 =
  534. {   &men1item3, 0, 40, 128, 11, ITEMTEXT|COMMSEQ|ITEMENABLED|HIGHCOMP,
  535.     0, (APTR)&men1item2text, NULL, 'R', NULL, MENUNULL
  536. };
  537.  
  538. struct IntuiText men1item1text =
  539. {   7, 0, COMPLEMENT, 0, 0, NULL, "Load file", NULL };
  540. struct MenuItem men1item1 =
  541. {   &men1item2, 0, 20, 128, 11, ITEMTEXT|COMMSEQ|ITEMENABLED|HIGHCOMP,
  542.     0, (APTR)&men1item1text, NULL, 'L', NULL, MENUNULL
  543. };
  544.  
  545. struct IntuiText men1item0text =
  546. {   7, 0, COMPLEMENT, 0, 0, NULL, "Load font", NULL };
  547. struct MenuItem men1item0 =
  548. {   &men1item1, 0, 0, 128, 11, ITEMTEXT|COMMSEQ|ITEMENABLED|HIGHCOMP,
  549.     0, (APTR)&men1item0text, NULL, 'F', NULL, MENUNULL
  550. };
  551.  
  552. struct Menu menu1 =
  553. {   &menu2, 80, 0, 80, 0, 0, "File", &men1item0 };
  554.  
  555. struct IntuiText men0item1text =
  556. {   7, 0, COMPLEMENT, 0, 0, NULL, "Quit", NULL };
  557. struct MenuItem men0item1 =
  558. {   NULL, 0, 20, 100, 11, ITEMTEXT|ITEMENABLED|HIGHCOMP,
  559.     0, (APTR)&men0item1text, NULL, NULL, NULL, MENUNULL
  560. };
  561.  
  562. struct IntuiText men0item0text =
  563. {   7, 0, COMPLEMENT, 0, 0, NULL, "Restart", NULL };
  564. struct MenuItem men0item0 =
  565. {   &men0item1, 0, 0, 100, 11, ITEMTEXT|ITEMENABLED|HIGHCOMP,
  566.     0, (APTR)&men0item0text, NULL, NULL, NULL, MENUNULL
  567. };
  568.  
  569. struct Menu menu0 =
  570. {   &menu1, 0, 0, 80, 0, 0, "Project", &men0item0 };
  571.  
  572. /* Arguments */
  573.  
  574. int arglen, argwb, argfilec;
  575. int argprint, argscreen, argiff, argint, argclosewb;
  576. char *argbuf, *argsize, *argmem;
  577. char *argfilev[] =
  578. {   (char *) &if0gadgbuff[0],
  579.     (char *) &if1gadgbuff[0],
  580.     (char *) &if2gadgbuff[0],
  581.     (char *) &if3gadgbuff[0],
  582.     (char *) &if4gadgbuff[0]
  583. };
  584. char *argifn =
  585.     (char *) &ifngadgbuff[0];
  586. char *argcon = "CON";
  587. char *argkey[] =
  588. {   "IFF",
  589.     "SCREEN",
  590.     "PRINTER",
  591.     "INTERACTIVE",
  592.     "SIZE",
  593.     "MEM",
  594.     "CLOSEWB",
  595.     "CONDEV",
  596.     NULL
  597. };
  598.  
  599. /* Lattice stuff for using Arp FPrintf/SPrintf */
  600.  
  601. LONG ArpFPrintf(BPTR, char*,);
  602. LONG ArpSPrintf(char *, char*,);
  603.  
  604. # pragma libcall ArpBase ArpFPrintf 00EA 98003
  605. # pragma libcall ArpBase ArpSPrintf 0282 98003
  606.  
  607. LONG __stdargs FPrintf(BPTR fh, char *format,)
  608. {   return  ArpFPrintf(fh, format, (&format)+1);
  609. }
  610.  
  611. LONG __stdargs SPrintf(char *string, char *format,)
  612. {   return  ArpSPrintf(string, format, (&format)+1);
  613. }
  614.  
  615. /* Startup code */
  616.  
  617. extern void main(int argc, char **argv);
  618.  
  619. void _main(char *line)
  620. {   struct DiskObject *diskobj;
  621.     char *diskname;
  622.     char *argv[32];
  623.     int argc;
  624.  
  625.     /* If this is a workbench startup construct the arguments string.  We
  626.      * find the name of our icon from the first argument.  Then we laod the
  627.      * icon and look for an ARGS string in the tooltypes.  We concatenate
  628.      * the program name and the arguments into an Alloc'ed buffer */
  629.  
  630.     if (WBenchMsg && WBenchMsg->sm_NumArgs)
  631.     {   diskname = WBenchMsg->sm_ArgList[0].wa_Name;
  632.         line = NULL;
  633.         IconBase = (struct IconBase *) OpenLibrary("icon.library", 0);
  634.         if (IconBase)
  635.         {   diskobj = GetDiskObject(diskname);
  636.             line = FindToolType(diskobj->do_ToolTypes, "ARGS");
  637.         }
  638.         if (line)
  639.         {   arglen = strlen(diskname) + strlen(line) + 2;
  640.             argbuf = AllocMem(arglen, MEMF_CLEAR);
  641.         }
  642.         if (argbuf)
  643.         {   strcpy(argbuf, diskname);
  644.             strcat(argbuf, " ");
  645.             strcat(argbuf, line);
  646.         }
  647.         line = argbuf;
  648.         if (diskobj)
  649.             FreeDiskObject(diskobj);
  650.         if (IconBase)
  651.             CloseLibrary((struct Library *) IconBase);
  652.     }
  653.  
  654.     /* Parse the arguments to break words and strip quotes.  N.B. the
  655.      * main program can determine that the arument was quoted by inspecting
  656.      * the preceeding character */
  657.  
  658.     argc = 0;
  659.     if (line == NULL) goto endline;
  660.     for (;;)
  661.     {   while (*line == ' ' || *line == '\t' || *line == '\n') line++;
  662.         if (*line == 0) break;
  663.         if (argc == 32)
  664.         {   argc = 0;
  665.             goto endline;
  666.         }
  667.         if (*line == '"')
  668.         {   argv[argc] = ++line;
  669.             while (*line != '"')
  670.             {   if (*line == 0)
  671.                 {   argc = 0;
  672.                     goto endline;
  673.                 }
  674.                 line++;
  675.             }
  676.         }
  677.         else
  678.         {   argv[argc] = line;
  679.             while (*line != ' ' && *line != '\t' && *line != '\n')
  680.             {   if (*line == 0)
  681.                 {   argc++;
  682.                     goto endline;
  683.                 }
  684.                 line++;
  685.             }
  686.         }
  687.         *line++ = 0;
  688.         argc++;
  689.     }
  690. endline:
  691.  
  692.     /* Set up the standard input/output files */
  693.  
  694.     if (WBenchMsg) /* Workbench startup, no files */
  695.     {   argwb = 1;
  696.     }
  697.     else           /* CLI startup, open stderr */
  698.     {   errfh = Open("*", MODE_OLDFILE);
  699.         if (errfh == NULL)
  700.         {   retcode = 20;
  701.             goto tidyexit;
  702.         }
  703.     }
  704.  
  705.     /* Call the main program  */
  706.  
  707.     main(argc, argv);
  708.  
  709.     /* Tidy up and exit */
  710.  
  711. tidyexit:
  712.     if (argbuf) FreeMem(argbuf, arglen);
  713.     if (errfh) Close(errfh);
  714.  
  715.     XCEXIT(retcode);
  716. }
  717.  
  718. /* Main program */
  719.  
  720. void main(int argc, char **argv)
  721. {   struct Message *msg;
  722.     struct Gadget *gadget;
  723.     char *s;
  724.     int *ip, i, ch, l;
  725.     int xsize, ysize, ssize, xden, yden, pden;
  726.  
  727.     process = (struct Process *) FindTask(NULL);
  728.     syswindow = (struct Window *) process->pr_WindowPtr;
  729.  
  730.     /* Open the libraries */
  731.  
  732.     GfxBase =
  733.         (struct GfxBase *)       OpenLibrary("graphics.library", 0);
  734.     IntuitionBase =
  735.         (struct IntuitionBase *) OpenLibrary("intuition.library", 0);
  736.     ArpBase =
  737.         (struct ArpBase *)       OpenLibrary("arp.library", 39);
  738.     if (GfxBase == NULL || IntuitionBase == NULL || ArpBase == NULL)
  739.     {   errmsg("can't open libraries (you need arp.library V39+)");
  740.         goto errorexit;
  741.     }
  742. # ifndef STATICLINK
  743.     PSbase = OpenLibrary("post.library", 0);
  744.     if (PSbase == NULL)
  745.     {   errmsg("can't open post.library");
  746.         goto errorexit;
  747.     }
  748. # endif
  749.  
  750.     /* Parse the arguments and keywords.  See the usage string below */
  751.  
  752.     if (argc == 0) goto badargs;
  753.     argc--;
  754.     argv++;
  755.     if (argc == 0 || argwb) argint = 1;
  756.     if (argc == 1 && (strcmp(*argv, "?") == 0)) goto usage;
  757.  
  758.     while (argc--)
  759.     {   s = *argv++;
  760.         i = -1;
  761.         if (s[-1] != '"')
  762.             for (;;)
  763.             {   i++;
  764.                 if (argkey[i] == NULL)
  765.                 {   i = -1;
  766.                     break;
  767.                 }
  768.                 if (stricmp(s, argkey[i]) == 0) break;
  769.             }
  770.         switch (i)
  771.         {   case 0:    /* IFF */
  772.                 if (argc == 0 || strlen(*argv) >= 80) goto badargs;
  773.                 argc--;
  774.                 argiff = 1;
  775.                 strcpy(argifn, *argv++);
  776.                 break;
  777.  
  778.             case 1:    /* SCREEN */
  779.                 argscreen = 1;
  780.                 break;
  781.  
  782.             case 2:    /* PRINTER */
  783.                 argprint = 1;
  784.                 break;
  785.  
  786.             case 3:    /* INTERACTIVE */
  787.                 argint = 1;
  788.                 break;
  789.  
  790.             case 4:    /* SIZE */
  791.                 if (argc == 0) goto badargs;
  792.                 argc--;
  793.                 argsize = *argv++;
  794.                 break;
  795.  
  796.             case 5:    /* MEM */
  797.                 if (argc == 0) goto badargs;
  798.                 argc--;
  799.                 argmem = *argv++;
  800.                 break;
  801.  
  802.             case 6:    /* CLOSEWB */
  803.                 argclosewb = 1;
  804.                 break;
  805.  
  806.             case 7:    /* CONDEV */
  807.                 if (argc == 0) goto badargs;
  808.                 argc--;
  809.                 argcon = *argv++;
  810.                 break;
  811.  
  812.             default:
  813.                 if (argfilec == 5 || strlen(s) >= 80) goto badargs;
  814.                 strcpy(argfilev[argfilec++], s);
  815.         }
  816.     }
  817.     if (!argscreen && !argiff && !argint)  argprint = 1;
  818.     if (argscreen) argint = 1;
  819.  
  820.     /* Set up the default page size.  For printer output we get the defaults
  821.      * from preferences; otherwise we default to an 8 by 11 inch page at 75
  822.      * dpi. with 3 colour planes */
  823.  
  824.     bitmap.BytesPerRow = 1;
  825.     bitmap.Rows = 1;
  826.     bitmap.Flags = 0;
  827.     bitmap.Depth = parm.page.depth = 3;
  828.     if (argprint)
  829.     {   setprinter();
  830.         if (prport == NULL)
  831.         {   errmsg("can't open printer device");
  832.             goto errorexit;
  833.         }
  834.     }
  835.     else
  836.     {   parm.page.xsize = 8 * 75;
  837.         parm.page.ysize = 11 * 75;
  838.         parm.page.xden = parm.page.yden = 75;
  839.     }
  840.     parm.page.ydir = -1;
  841.  
  842.     /* Parse the "SIZE xyd..s..p.bc." option. */
  843.  
  844.     xsize = ysize = ssize = xden = yden = pden = 0;
  845.     if (argsize)
  846.     {   s = argsize;
  847.         for (;;)
  848.         {   ch = *s++;
  849.             if (ch == 0) break;
  850.             ch = tolower(ch);
  851.             switch (ch)
  852.             {   case 'x':
  853.                     if (tolower(*s) == 'd')
  854.                     {   s++;
  855.                         ip = &xden;
  856.                     }
  857.                     else
  858.                         ip = &xsize;
  859.                     break;
  860.  
  861.                 case 'y':
  862.                     if (tolower(*s) == 'd')
  863.                     {   s++;
  864.                         ip = &yden;
  865.                     }
  866.                     else
  867.                         ip = &ysize;
  868.                     break;
  869.  
  870.                 case 's':
  871.                     ip = &ssize;
  872.                     break;
  873.  
  874.                 case 'p':
  875.                     ip = &pden;
  876.                     break;
  877.  
  878.                 case 'd':
  879.                 {   if (!strtoint(&s, &xden)) goto badvalue;
  880.                     yden = xden;
  881.                     continue;
  882.                 }
  883.  
  884.                 case 'b':
  885.                     parm.page.depth = 1;
  886.                     continue;
  887.  
  888.                 case 'c':
  889.                     ch = *s;
  890.                     if      (ch == '3')
  891.                     {   s++;
  892.                         parm.page.depth = 3;
  893.                     }
  894.                     else if (ch == '4')
  895.                     {   s++;
  896.                         parm.page.depth  = 4;
  897.                     }
  898.                     else
  899.                         parm.page.depth = 3;
  900.                     continue;
  901.  
  902.                 default:
  903.                     goto badvalue;
  904.             }
  905.             if (!strtoint(&s, ip)) goto badvalue;
  906.         }
  907.     }
  908.     if (xden != 0) parm.page.xden = xden;
  909.     if (yden != 0) parm.page.yden = yden;
  910.     if (xsize != 0) parm.page.xsize = xsize;
  911.     if (ysize != 0) parm.page.ysize = ysize;
  912.     if (pden != 0)
  913.     {   prden = pden;
  914.         if (argprint) setprintden();
  915.     }
  916.  
  917.     /* Set up the default memory sizes */
  918.  
  919.     parm.memvlen = 280000;
  920.     parm.memflen =  60000;
  921.     parm.memllen =  60000;
  922.     parm.memhlen =  20000;
  923.  
  924.     /* Parse the "MEM fhlv.." option */
  925.  
  926.     if (argmem)
  927.     {   s = argmem;
  928.         for (;;)
  929.         {   ch = *s++;
  930.             if (ch == 0) break;
  931.             ch = tolower(ch);
  932.             switch (ch)
  933.             {   case 'f':
  934.                     ip = &parm.memflen;
  935.                     break;
  936.  
  937.                 case 'h':
  938.                     ip = &parm.memhlen;
  939.                     break;
  940.  
  941.                 case 'l':
  942.                     ip = &parm.memllen;
  943.                     break;
  944.  
  945.                 case 'v':
  946.                     ip = &parm.memvlen;
  947.                     break;
  948.  
  949.                 default:
  950.                     goto badvalue;
  951.             }
  952.             if (!strtoint(&s, ip)) goto badvalue;
  953.         }
  954.     }
  955.  
  956.     /* We only need the file requestors if we are interactive */
  957.  
  958.     if (argint)
  959.     {   filereq1 = ArpAllocFreq();
  960.         filereq2 = ArpAllocFreq();
  961.         if (filereq1 == NULL || filereq2 == NULL)
  962.         {   errmsg("can't get file requestors");
  963.             goto errorexit;
  964.         }
  965.     }
  966.  
  967.     /* We seem to have to explicitly load the font from the disk before
  968.      * Intuition can be depended upon to use it */
  969.  
  970.     if (argint)
  971.     {  DiskfontBase = OpenLibrary("diskfont.library", 0);
  972.        if (DiskfontBase)
  973.        {   textfont = OpenDiskFont(&topaz11);
  974.            CloseLibrary(DiskfontBase);
  975.        }
  976.        if (textfont == NULL)
  977.        {   errmsg("can't find font topaz/11");
  978.            goto errorexit;
  979.        }
  980.     }
  981.  
  982.     /* Set up the color map according to the number of bitplanes */
  983.  
  984. setcmap:
  985.     restarterror = 0;
  986.     if (!argint) newscreen.Depth = parm.page.depth;
  987.     colormap.Count = 1 << newscreen.Depth;
  988.     if      (newscreen.Depth == 1)
  989.         colormap.ColorTable = (APTR) bcolors;
  990.     else
  991.         colormap.ColorTable = (APTR) ccolors;
  992.  
  993.     /* Set up the screen size, adjusting for interlace.  Open the screen
  994.      * and load the color map  */
  995.  
  996.     if (argint)
  997.     {   newscreen.Width = GfxBase->NormalDisplayColumns;
  998.         newscreen.Height = GfxBase->NormalDisplayRows * 2;
  999.         if (newscreen.Width < 400) newscreen.Width = 400;
  1000.         if (newscreen.Height < 300) newscreen.Width = 300;
  1001.         screen = OpenScreen(&newscreen);
  1002.         if (screen == NULL)
  1003.         {   errmsg("can't open screen");
  1004.             goto errorexit;
  1005.         }
  1006.         newerrwindow.Screen = screen;
  1007.         newreqwindow.Screen = screen;
  1008.         newbitwindow.Screen = screen;
  1009.         newintwindow.Screen = screen;
  1010.         LoadRGB4(&screen->ViewPort,
  1011.                  (short *) colormap.ColorTable, colormap.Count);
  1012.         newerrwindow.Width = newscreen.Width;
  1013.         errwindow = OpenWindow(&newerrwindow);
  1014.         if (errwindow == NULL)
  1015.         {   errmsg("can't open error window");
  1016.             goto errorexit;
  1017.         }
  1018.         process->pr_WindowPtr = (APTR) errwindow;
  1019.     }
  1020.     restarterror = 1;
  1021.  
  1022. restart:
  1023.     if (fatalerror) goto tidyexit;
  1024.     retcode = 0;
  1025.     tidyup();
  1026.  
  1027.     if (argint)
  1028.     {   if (argclosewb) CloseWorkBench();
  1029.         if (requested == 0)
  1030.         {
  1031.             /* Put up the parameters requestor (window) */
  1032.  
  1033.             setreqgadgets();
  1034.             newreqwindow.IDCMPFlags = GADGETUP|GADGETDOWN;
  1035.             reqwindow = OpenWindow(&newreqwindow);
  1036.             if (reqwindow == NULL)
  1037.             {   errmsg("can't open parameters window");
  1038.                 goto restart;
  1039.             }
  1040.             PrintIText(reqwindow->RPort, &itext3, 0, 0);
  1041.  
  1042.             /* Loop handling gadget messages */
  1043.  
  1044.             for (;;)
  1045.             {   WaitPort(reqwindow->UserPort);
  1046.                 while (msg = GetMsg(reqwindow->UserPort))
  1047.                 {   gadget = (struct Gadget *)
  1048.                         ((struct IntuiMessage *) msg)->IAddress;
  1049.                     i = gadget->GadgetID;
  1050.                     switch (i)
  1051.                     {   case GADGOK:
  1052.                         case GADGCAN:
  1053.                             goto closereq;
  1054.  
  1055.                         case GADGPRI:
  1056.                             argprint = getgadgbool(&prigadg);
  1057.                             if (argprint)
  1058.                             {    setprinter();
  1059.                                  if (prport == NULL)
  1060.                                  {   argprint = 0;
  1061.                                      errmsg("can't open printer device");
  1062.                                      i = GADGRST;
  1063.                                      goto closereq;
  1064.                                  }
  1065.                             }
  1066.                             goto setgadg;
  1067.  
  1068.                         case GADGPD1: case GADGPD2: case GADGPD3:
  1069.                         case GADGPD4: case GADGPD5: case GADGPD6:
  1070.                         case GADGPD7:
  1071.                             if (argprint)
  1072.                             {   prden = i - (GADGPD1 - 1);
  1073.                                 setprintden();
  1074.                                 goto setgadg;
  1075.                             }
  1076.                             break;
  1077.  
  1078.                         case GADGBW:
  1079.                             parm.page.depth = 1;
  1080.                             goto setgadg;
  1081.  
  1082.                         case GADGC3:
  1083.                             parm.page.depth = 3;
  1084.                             goto setgadg;
  1085.  
  1086.                         case GADGC4:
  1087.                             parm.page.depth = 4;
  1088.  
  1089. setgadg:                    setreqgadgets();
  1090.                     }
  1091.                     ReplyMsg(msg);
  1092.                 }
  1093.             }
  1094.  
  1095.             /* Close the requester window */
  1096.  
  1097. closereq:   ModifyIDCMP(reqwindow, CLOSEWINDOW);
  1098.             while (msg)
  1099.             {   ReplyMsg(msg);
  1100.                 msg = GetMsg(reqwindow->UserPort);
  1101.             }
  1102.             CloseWindow(reqwindow);
  1103.             reqwindow = NULL;
  1104.  
  1105.             if (i == GADGCAN) goto tidyexit;
  1106.             if (i == GADGRST) goto restart;
  1107.  
  1108.             getreqgadgets();
  1109.  
  1110.             /* If we have changed our mind about the number of bitplanes
  1111.              * close the screen and go back to reopen it with the new depth
  1112.              */
  1113.  
  1114.             if (parm.page.depth != newscreen.Depth)
  1115.             {   process->pr_WindowPtr = (APTR) syswindow;
  1116.                 CloseWindow(errwindow);
  1117.                 errwindow = NULL;
  1118.                 CloseScreen(screen);
  1119.                 screen = NULL;
  1120.                 newscreen.Depth = parm.page.depth;
  1121.                 requested = 1;
  1122.                 goto setcmap;
  1123.             }
  1124.         }
  1125.         requested = 0;
  1126.     }
  1127.  
  1128.     /* Set the size of the interactive windows */
  1129.  
  1130.     if (argint)
  1131.     {   newbitwindow.Width = newscreen.Width;
  1132.         newbitwindow.Height = newscreen.Height -
  1133.             newintwindow.TopEdge - newintwindow.Height;
  1134.         newbitwindow.TopEdge = newscreen.Height -
  1135.             newbitwindow.Height;
  1136.         newintwindow.Width = newscreen.Width;
  1137.         newintwindow.MaxHeight = newscreen.Height -
  1138.             newintwindow.TopEdge - newbitwindow.MinHeight;
  1139.  
  1140.     /* Locate the visible part of the bitmap within its window, adjusting
  1141.      * for the borders */
  1142.  
  1143.         winxbase = 4;
  1144.         winybase = 2;
  1145.         winxsize = newbitwindow.Width - 22;
  1146.         winysize = newbitwindow.Height - 12;
  1147.  
  1148.     /* Set the page size.  It must not be smaller than the interior of the
  1149.      * interactive window.  We may not need the horizontal scroll bar.  Each
  1150.      * bitmap row must start on a word boundary */
  1151.  
  1152.         if (parm.page.xsize <= winxsize)
  1153.         {   winysize += 8;
  1154.             vscrollgadg.NextGadget = 0;
  1155.             vscrollgadg.Height = 0;
  1156.         }
  1157.         else
  1158.         {   vscrollgadg.NextGadget = &hscrollgadg;
  1159.             vscrollgadg.Height = -8;
  1160.         }
  1161.         if (parm.page.xsize < winxsize) parm.page.xsize = winxsize;
  1162.         if (parm.page.ysize < winysize) parm.page.ysize = winysize;
  1163.     }
  1164.     parm.page.ybase = 0;
  1165.     parm.page.yheight = parm.page.ysize;
  1166.     if (!argint)
  1167.         if (ssize != 0 && ssize < parm.page.ysize) parm.page.ysize = ssize;
  1168.     if (parm.page.xsize == 0 || parm.page.ysize == 0)
  1169.     {   errmsg("page size not set in preferences");
  1170.         goto restart;
  1171.     }
  1172.     parm.page.xbytes = (parm.page.xsize + 15) >> 3 & 0xfffffffe;
  1173.     parm.page.len = parm.page.xbytes * parm.page.ysize;
  1174.  
  1175.     /* Allocate the page buffer.  It  must be in chip memory if we are
  1176.      * outputting to a screen */
  1177.  
  1178.     for (i= 0; i < parm.page.depth; i++)
  1179.     {   if ((parm.page.buf[i] = AllocMem(parm.page.len,
  1180.                  (argscreen ? MEMF_CHIP|MEMF_CLEAR :
  1181.                               MEMF_PUBLIC|MEMF_CLEAR))) == NULL)
  1182.         {   errmsg("can't get page buffer");
  1183.             goto restart;
  1184.         }
  1185.     }
  1186.  
  1187.     /* Initialise the bitmap */
  1188.  
  1189.     bitmap.BytesPerRow = parm.page.xbytes;
  1190.     bitmap.Rows = parm.page.ysize;
  1191.     bitmap.Flags = 0;
  1192.     bitmap.Depth = parm.page.depth;
  1193.     memcpy((char *) bitmap.Planes, (char *) parm.page.buf,
  1194.            sizeof bitmap.Planes);
  1195.  
  1196.     /* For interactive working, set up the windows */
  1197.  
  1198.     if (argint)
  1199.     {
  1200.         /* Finish initialising the gadgets and open the windows */
  1201.  
  1202.         hscrollinfo.HorizPot = 0;
  1203.         vscrollinfo.VertPot = 0xffff;
  1204.         hscrollinfo.HorizBody = (0xffff * winxsize) / parm.page.xsize;
  1205.         vscrollinfo.VertBody = (0xffff * winysize) / parm.page.ysize;
  1206.         winxpos = 0;
  1207.         winypos = parm.page.ysize - winysize;
  1208.         bitwindow = OpenWindow(&newbitwindow);
  1209.         intwindow = OpenWindow(&newintwindow);
  1210.         if (bitwindow == NULL || intwindow == NULL)
  1211.         {   errmsg("can't open windows");
  1212.             goto restart;
  1213.         }
  1214.  
  1215.         /* Set up new console streams.  Black on white characters */
  1216.  
  1217.         SPrintf((char *) undobuff, "%s:W%lx\0", argcon, intwindow);
  1218.         confh = Open((char *) undobuff, MODE_OLDFILE);
  1219.         if (confh == NULL)
  1220.         {   errmsg("can't open console device (you need ConMan V1.3+)");
  1221.             goto restart;
  1222.         }
  1223.         FPrintf(confh, "\x9b\x33\x37\x6d");
  1224.     }
  1225.  
  1226.         /* Create the menu handler task */
  1227.  
  1228.     if (argint)
  1229.     {   mainport = CreatePort(NULL, 0);
  1230.         if (mainport)
  1231.         {   menumsg.ExecMessage.mn_ReplyPort = mainport;
  1232.             menumsg.action = PSACTOPEN;
  1233.             menumsg.bitmap = &bitmap;
  1234.             menutask = CreateTask("post.menu", 6, (APTR) menuproc, 2000);
  1235.         }
  1236.         if (menutask)
  1237.             sendmenu(PSACTOPEN);
  1238.         if (menutask == NULL)
  1239.         {   errmsg("can't create menu handler");
  1240.             goto restart;
  1241.         }
  1242.     }
  1243.  
  1244.     /* Initialise for interpretation */
  1245.  
  1246.     insertbreak();
  1247.     SetExcept(~0, SIGBREAKF_CTRL_C);
  1248.     breakset = 1;
  1249.     insertftrap();
  1250.     ftrapset = 1;
  1251.  
  1252. # ifndef STATICLINK
  1253.     parm.flushfunc = (APTR) flushpage;
  1254.     parm.copyfunc = (APTR) copypage;
  1255. # endif
  1256.  
  1257.     if (argint)
  1258.     {   parm.infh = confh;
  1259.         parm.outfh = confh;
  1260.         parm.errfh = confh;
  1261.     }
  1262.     else
  1263.     {   parm.infh = Input();
  1264.         parm.outfh = Output();
  1265.         parm.errfh = errfh;
  1266.     }
  1267.  
  1268.     arec = PScreateact(&parm);
  1269.     if (arec == 0)
  1270.     {   errmsg("can't get memory");
  1271.         retcode = 20;
  1272.         goto restart;
  1273.     }
  1274.     if ((unsigned) arec <= errmax) retcode = 10;
  1275.  
  1276.     /* Interpret the argument files */
  1277.  
  1278.     for (i = 0; i < 5; i++)
  1279.     {   s = argfilev[i];
  1280.         if (s[0] != 0)
  1281.         {   if (retcode != 0) break;
  1282.             errcode =
  1283.                 PSintstring(arec, s, -1, PSFLAGFILE|PSFLAGCLEAR|PSFLAGERASE);
  1284.             if (errcode) retcode = 10;
  1285.         }
  1286.     }
  1287.  
  1288.     /* Execute menu commands */
  1289.  
  1290.     if (argint)
  1291.     {   for (;;)
  1292.         {   sendmenu(retcode == 0 ? PSACTCOMMAND : PSACTEXIT);
  1293.             s = menumsg.string;
  1294.             switch (menumsg.command)
  1295.             {   case PSCOMQUIT:
  1296.                     goto quit;
  1297.  
  1298.                 case PSCOMRESTART:
  1299.                     PSdeleteact(arec);
  1300.                     arec = 0;
  1301.                     goto restart;
  1302.  
  1303.                 case PSCOMFILEF:
  1304.                     i = PSFLAGFILE|PSFLAGCLEAR|PSFLAGERASE;
  1305.                     strcpy(filereq1->fr_Dir, "PSFonts:");
  1306.                     filereq = filereq1;
  1307.                     filereq->fr_Hail = hailfilef;
  1308.                     goto freq;
  1309.  
  1310.                 case PSCOMFILEL:
  1311.                     i = PSFLAGFILE|PSFLAGCLEAR|PSFLAGERASE;
  1312.                     filereq = filereq2;
  1313.                     filereq->fr_Hail = hailfilen;
  1314.                     goto freq;
  1315.  
  1316.                 case PSCOMFILER:
  1317.                     i = PSFLAGFILE|PSFLAGCLEAR|PSFLAGERASE|PSFLAGSAVE;
  1318.                     filereq = filereq2;
  1319.                     filereq->fr_Hail = hailfiles;
  1320. freq:               filereq->fr_Window = intwindow;
  1321.                     filereq->fr_FuncFlags |= (FRF_NewIDCMP|FRF_DoColor);
  1322.                     filereq->fr_LeftEdge = 170;
  1323.                     filereq->fr_TopEdge = 150;
  1324.                     if (FileRequest(filereq) == NULL) break;
  1325.                     l = strlen(filereq->fr_Dir);
  1326.                     TackOn(filereq->fr_Dir, filereq->fr_File);
  1327.                     PSintstring(arec, filereq->fr_Dir, -1, i);
  1328.                     filereq->fr_Dir[l] = 0;
  1329.                     break;
  1330.  
  1331.                 case PSCOMINTER:
  1332.                     PSintstring(arec, "%stdin", -1, 
  1333.                         PSFLAGFILE|PSFLAGCLEAR|PSFLAGERASE|PSFLAGSAVE|
  1334.                         PSFLAGINTER);
  1335.                     break;
  1336.             }
  1337.         }
  1338.     }
  1339.  
  1340. quit:
  1341.     PSdeleteact(arec);
  1342.     arec = 0;
  1343.     goto tidyexit;
  1344.  
  1345.     /* Argument errors and usage query */
  1346.  
  1347. badargs:
  1348.     errmsg("arguments bad, or value missing or too long");
  1349.     goto badusage;
  1350.  
  1351. badvalue:
  1352.     errmsg("argument bad value");
  1353.  
  1354. badusage:
  1355.     retcode = 20;
  1356.  
  1357. usage:
  1358.     if (!argwb) FPrintf(errfh, "post: usage:\n"
  1359.     "    post [files...] [IFF file] [SCREEN] [PRINTER] [INTERACTIVE]\n"
  1360.     "         [SIZE xyd..s..p.bc.] [MEM fhlv..] [CLOSEWB] [CONDEV con]\n");
  1361.     goto tidyexit;
  1362.  
  1363.     /* Tidy up and exit */
  1364.  
  1365. errorexit:
  1366.     retcode = 20;
  1367.  
  1368. tidyexit:
  1369.     tidyup();
  1370.  
  1371.     process->pr_WindowPtr = (APTR) syswindow;
  1372.     if (errwindow) CloseWindow(errwindow);
  1373.     if (screen) CloseScreen(screen);
  1374.  
  1375.     if (textfont) CloseFont(textfont);
  1376.  
  1377.     if (propen) CloseDevice((struct IORequest *) &prreq);
  1378.     if (prport) DeletePort(prport);
  1379.  
  1380. # ifndef STATICLINK
  1381.     if (PSbase)  CloseLibrary(PSbase);
  1382. # endif
  1383.     if (ArpBase) CloseLibrary((struct Library *) ArpBase);
  1384.     if (GfxBase) CloseLibrary((struct Library *) GfxBase);
  1385.     if (IntuitionBase)
  1386.     {   OpenWorkBench();
  1387.         CloseLibrary((struct Library *) IntuitionBase);
  1388.     }
  1389. }
  1390.  
  1391. /* Display an error requestor or message */
  1392.  
  1393. struct IntuiText bodytext2 =
  1394. {   AUTOFRONTPEN, AUTOBACKPEN, AUTODRAWMODE,
  1395.     AUTOLEFTEDGE + 32, AUTOTOPEDGE + 11,
  1396.     AUTOITEXTFONT, NULL, NULL };
  1397. struct IntuiText bodytext =
  1398. {   AUTOFRONTPEN, AUTOBACKPEN, AUTODRAWMODE,
  1399.     AUTOLEFTEDGE, AUTOTOPEDGE,
  1400.     AUTOITEXTFONT, POSTVER " Error", &bodytext2 };
  1401. struct IntuiText postext =
  1402. {   AUTOFRONTPEN, AUTOBACKPEN, AUTODRAWMODE,
  1403.     AUTOLEFTEDGE, AUTOTOPEDGE,
  1404.     AUTOITEXTFONT, "RETRY", NULL };
  1405. struct IntuiText negtext =
  1406. {   AUTOFRONTPEN, AUTOBACKPEN, AUTODRAWMODE,
  1407.     AUTOLEFTEDGE, AUTOTOPEDGE,
  1408.     AUTOITEXTFONT, "CANCEL", NULL };
  1409.  
  1410. void errmsg(char *string)
  1411. {   int width;
  1412.     if (IntuitionBase && (errwindow || argwb))
  1413.     {   bodytext2.IText = string;
  1414.         width = IntuiTextLength(&bodytext2) + 70;
  1415.         if (width < 200) width = 200;
  1416.         if (!AutoRequest(errwindow, &bodytext,
  1417.                 (restarterror ? &postext : NULL), &negtext,
  1418.                 0, 0, width, 70))
  1419.             fatalerror = 1;
  1420.         return;
  1421.     }
  1422.     if (!argwb)
  1423.     {   FPrintf(errfh, "post: %s\n", string);
  1424.         fatalerror = 1;
  1425.         return;
  1426.     }
  1427.     fatalerror = 1;
  1428. }
  1429.  
  1430. /* Tidy up */
  1431.  
  1432. void tidyup(void)
  1433. {   int i;
  1434.  
  1435.     if (breakset)
  1436.     {   SetExcept(0, SIGBREAKF_CTRL_C);
  1437.         deletebreak();
  1438.         breakset = 0;
  1439.     }
  1440.     if (ftrapset)
  1441.     {   deleteftrap();
  1442.         ftrapset = 0;
  1443.     }
  1444.  
  1445.     if (menuport)
  1446.         sendmenu(PSACTCLOSE);
  1447.     if (mainport)
  1448.     {   DeletePort(mainport);
  1449.         mainport = NULL;
  1450.     }
  1451.  
  1452.     if (confh)
  1453.     {   Close(confh);
  1454.         confh = NULL;
  1455.     }
  1456.  
  1457.     /* N.B. some versions of ConMan close the window themselves, so we
  1458.      * don't close the interactive window it it appears to have been
  1459.      * closed already */
  1460.  
  1461.     if (bitwindow)
  1462.     {   CloseWindow(bitwindow);
  1463.         bitwindow = NULL;
  1464.     }
  1465.     if (intwindow)
  1466.     {   if (screen->FirstWindow == intwindow ||
  1467.             errwindow->NextWindow == intwindow) CloseWindow(intwindow);
  1468.         intwindow = NULL;
  1469.     }
  1470.  
  1471.     for (i = 0; i < parm.page.depth; i++)
  1472.         if (parm.page.buf[i])
  1473.         {   FreeMem(parm.page.buf[i], parm.page.len);
  1474.             parm.page.buf[i] = NULL;
  1475.         }
  1476. }
  1477.  
  1478. /* Open the printer device and set up the page size */
  1479.  
  1480. void setprinter(void)
  1481. {   if (propen == 0)
  1482.     {   if (OpenDevice("printer.device", 0,
  1483.                        (struct IOReqest *) &prreq, 0) != 0)
  1484.             return;
  1485.         propen = 1;
  1486.     }
  1487.     if (prport == NULL)
  1488.     {   prport = CreatePort(NULL, 0);
  1489.         if (prport == NULL) return;
  1490.         prreq.io_Message.mn_ReplyPort = prport;
  1491.         prsig = 1 << prport->mp_SigBit;
  1492.         prdata = (struct PrinterData *) prreq.io_Device;
  1493.         prextdata = &prdata->pd_SegmentData->ps_PED;
  1494.         prprefs = &prdata->pd_Preferences;
  1495.         prden = prprefs->PrintDensity;
  1496.     }
  1497.     if ((prprefs->PrintShade & SHADE_COLOR) == 0) parm.page.depth = 1;
  1498.     setprintden();
  1499. }
  1500.  
  1501. /* Set the printer density */
  1502.  
  1503. void setprintden(void)
  1504. {   int pxsize, pysize;
  1505.  
  1506.     /* New density, call the device driver to change its extended data.  No
  1507.      * error check */
  1508.  
  1509.     if (prden > 7) prden = 7;
  1510.     if (prden != prprefs->PrintDensity)
  1511.     {   prreq.io_Command = PRD_DUMPRPORT;
  1512.         prrast.BitMap = &bitmap;
  1513.         prreq.io_RastPort = &prrast;
  1514.         prreq.io_ColorMap = (struct ColorMap *) &colormap;
  1515.         prreq.io_Modes = 0;
  1516.         prreq.io_SrcX = 0;
  1517.         prreq.io_SrcY = 0;
  1518.         prreq.io_SrcWidth = 1;
  1519.         prreq.io_SrcHeight = 1;
  1520.         prreq.io_DestCols = 1;
  1521.         prreq.io_DestRows = 1;
  1522.         prreq.io_Special = (SPECIAL_DENSITY1 * prden) | SPECIAL_NOPRINT;
  1523.         prprefs->PrintDensity = prden;
  1524.         DoIO((struct IORequest *) &prreq);
  1525.     }
  1526.  
  1527.     /* Extract the page size and density from the printer device preferences
  1528.      * and extended data */
  1529.  
  1530.     parm.page.xden = prextdata->ped_XDotsInch;
  1531.     parm.page.yden = prextdata->ped_YDotsInch;
  1532.     if      (prprefs->PrintFlags & PIXEL_DIMENSIONS)
  1533.     {   pxsize = prprefs->PrintMaxWidth;
  1534.         pysize = prprefs->PrintMaxHeight;
  1535.     }
  1536.     else if (prprefs->PrintFlags &
  1537.                 (BOUNDED_DIMENSIONS|ABSOLUTE_DIMENSIONS))
  1538.     {   pxsize = prprefs->PrintMaxWidth * parm.page.xden / 10;
  1539.         pysize = prprefs->PrintMaxHeight * parm.page.yden / 10;
  1540.     }
  1541.     if (pxsize != 0) parm.page.xsize = pxsize;
  1542.     if (pysize != 0) parm.page.ysize = pysize;
  1543. }
  1544.  
  1545. /* Set all requester gadgets */
  1546.  
  1547. void setreqgadgets(void)
  1548. {   setgadgbool(&bwgadg, (parm.page.depth == 1));
  1549.     setgadgbool(&c3gadg, (parm.page.depth == 3));
  1550.     setgadgbool(&c4gadg, (parm.page.depth == 4));
  1551.     setgadgbool(&pd1gadg, (prden == 1));
  1552.     setgadgbool(&pd2gadg, (prden == 2));
  1553.     setgadgbool(&pd3gadg, (prden == 3));
  1554.     setgadgbool(&pd4gadg, (prden == 4));
  1555.     setgadgbool(&pd5gadg, (prden == 5));
  1556.     setgadgbool(&pd6gadg, (prden == 6));
  1557.     setgadgbool(&pd7gadg, (prden == 7));
  1558.     setgadgint(&xgadg, parm.page.xsize);
  1559.     setgadgint(&ygadg, parm.page.ysize);
  1560.     setgadgint(&xdgadg, parm.page.xden);
  1561.     setgadgint(&ydgadg, parm.page.yden);
  1562.     if (reqwindow == NULL)
  1563.     {   setgadgbool(&prigadg, argprint);
  1564.         setgadgbool(&scrgadg, argscreen);
  1565.         setgadgbool(&iffgadg, argiff);
  1566.         setgadgbool(&cwbgadg, argclosewb);
  1567.         setgadgint(&mvgadg, parm.memvlen);
  1568.         setgadgint(&mfgadg, parm.memflen);
  1569.         setgadgint(&mlgadg, parm.memllen);
  1570.         setgadgint(&mhgadg, parm.memhlen);
  1571.     }
  1572.     enablegadg(&pd1gadg, argprint);
  1573.     enablegadg(&pd2gadg, argprint);
  1574.     enablegadg(&pd3gadg, argprint);
  1575.     enablegadg(&pd4gadg, argprint);
  1576.     enablegadg(&pd5gadg, argprint);
  1577.     enablegadg(&pd6gadg, argprint);
  1578.     enablegadg(&pd7gadg, argprint);
  1579. }
  1580.  
  1581. /* Get all requester gadgets */
  1582.  
  1583. void getreqgadgets(void)
  1584. {   argscreen = getgadgbool(&scrgadg);
  1585.     argiff = getgadgbool(&iffgadg);
  1586.     if (argifn[0] == 0) argiff = 0;
  1587.     parm.page.depth = getgadgbool(&bwgadg) ? 1 :
  1588.                       getgadgbool(&c3gadg) ? 3 : 4;
  1589.     argclosewb = getgadgbool(&cwbgadg);
  1590.     parm.page.xsize = getgadgint(&xgadg);
  1591.     parm.page.ysize = getgadgint(&ygadg);
  1592.     parm.page.xden = getgadgint(&xdgadg);
  1593.     parm.page.yden = getgadgint(&ydgadg);
  1594.     parm.memvlen = getgadgint(&mvgadg);
  1595.     parm.memflen = getgadgint(&mfgadg);
  1596.     parm.memllen = getgadgint(&mlgadg);
  1597.     parm.memhlen = getgadgint(&mhgadg);
  1598. }
  1599.  
  1600. /* Enable a gadget */
  1601.  
  1602. void enablegadg(struct Gadget *gadget, int enable)
  1603. {   if ((gadget->Flags & GADGDISABLED) != (enable ? 0 : GADGDISABLED))
  1604.     {   if (reqwindow)
  1605.             RemoveGadget(reqwindow, gadget);
  1606.         if (enable)
  1607.             gadget->Flags &= ~GADGDISABLED;
  1608.         else
  1609.             gadget->Flags |=  GADGDISABLED;
  1610.         if (reqwindow)
  1611.         {   AddGadget(reqwindow, gadget, 65535);
  1612.             RefreshGadgets(gadget, reqwindow, NULL);
  1613.         }
  1614.     }
  1615. }
  1616.  
  1617. /* Set the value of a boolean requester gadget */
  1618.  
  1619. void setgadgbool(struct Gadget *gadget, int value)
  1620. {   if (value == getgadgbool(gadget)) return;
  1621.     if (reqwindow)
  1622.         RemoveGadget(reqwindow, gadget);
  1623.     if (value)
  1624.         gadget->Flags |=  SELECTED;
  1625.     else
  1626.         gadget->Flags &= ~SELECTED;
  1627.     if (reqwindow)
  1628.     {   AddGadget(reqwindow, gadget, 65535);
  1629.         RefreshGadgets(gadget, reqwindow, NULL);
  1630.     }
  1631. }
  1632.  
  1633. /* Get the value of a boolean gadget */
  1634.  
  1635. int getgadgbool(struct Gadget *gadget)
  1636. {   return (gadget->Flags & SELECTED) != 0;
  1637. }
  1638.  
  1639. /* Set the value of an integer requester gadget */
  1640.  
  1641. void setgadgint(struct Gadget *gadget, int value)
  1642. {   struct StringInfo *info;
  1643.     int n;
  1644.     if (value == getgadgint(gadget)) return;
  1645.     if (reqwindow)
  1646.         RemoveGadget(reqwindow, gadget);
  1647.     info = (struct StringInfo *) gadget->SpecialInfo;
  1648.     info->LongInt = value;
  1649.     n = info->MaxChars - 1;
  1650.     undobuff[n] = 0;
  1651.     while (n)
  1652.     {   n--;
  1653.         undobuff[n] = (value % 10) + '0';
  1654.         value /= 10;
  1655.     }
  1656.     while (undobuff[n] == '0') n++;
  1657.     if (undobuff[n] == 0) n--;
  1658.     strcpy(info->Buffer, &undobuff[n]);
  1659.     if (reqwindow)
  1660.     {   AddGadget(reqwindow, gadget, 65535);
  1661.         RefreshGadgets(gadget, reqwindow, NULL);
  1662.     }
  1663. }
  1664.  
  1665. /* Get the value of an integer gadget */
  1666.  
  1667. int getgadgint(struct Gadget *gadget)
  1668. {   struct StringInfo *info = (struct StringInfo *) gadget->SpecialInfo;
  1669.     int value = info->LongInt;
  1670.     if (value < 0) value = 0;
  1671.     return value;
  1672. }
  1673.  
  1674. /* String to integer conversion; digits only, with error check */
  1675.  
  1676. int strtoint(char **sp, int *ip)
  1677. {   char *s = *sp;
  1678.     int i = 0;
  1679.     int ch;
  1680.     for (;;)
  1681.     {   ch = *s;
  1682.         if (ch < '0' || ch > '9') break;
  1683.         i = i * 10 + (ch - '0');
  1684.         s++;
  1685.     }
  1686.     if (s == *sp)
  1687.         return 0;
  1688.     else
  1689.     {   *sp = s;
  1690.         *ip = i;
  1691.         return 1;
  1692.     }
  1693. }
  1694.  
  1695. /* Send a mesage to the menu handler task */
  1696.  
  1697. void sendmenu(int action)
  1698. {   if (action != PSACTOPEN)
  1699.     {   menumsg.action = action;
  1700.         menumsg.result = retcode;
  1701.         menumsg.errnum = errcode;
  1702.         PutMsg(menuport, (struct Message *) &menumsg);
  1703.     }
  1704.     WaitPort(mainport);
  1705.     GetMsg(mainport);
  1706.     retcode = menumsg.result;
  1707. }
  1708.  
  1709. /* The menu handler task */
  1710.  
  1711. void __saveds menuproc(void)
  1712. {   struct Message *msg;
  1713.     char *title, *oldtitle, *savetitle;
  1714.     int pause;
  1715.     int height, i, j;
  1716.  
  1717.     title = titlestart;
  1718.     pause = 1;
  1719.     height = newintwindow.Height;
  1720.     msg = (struct Message *) &menumsg;
  1721.  
  1722.     /* Loop handling messages.  We access the initial message directly,
  1723.      * rather than getting it from the menu port, as we havn't created the
  1724.      * port yet */
  1725.  
  1726.     for (;;)
  1727.     {
  1728.         /* Message from main program */
  1729.  
  1730.         if ((struct PSmessage *) msg == &menumsg)
  1731.         {   switch (menumsg.action)
  1732.             {
  1733.                 /* Open the windows and initialise */
  1734.  
  1735.                 case PSACTOPEN:
  1736.                     menuport = CreatePort(NULL, 0);
  1737.                     if (menuport == NULL)
  1738.                     {   menumsg.result = 20;
  1739.                         goto end;
  1740.                     }
  1741.                     bitwindow->UserPort = menuport;
  1742.                     intwindow->UserPort = menuport;
  1743.                     ModifyIDCMP(bitwindow,
  1744.                             REFRESHWINDOW|ACTIVEWINDOW|GADGETUP);
  1745.                     ModifyIDCMP(intwindow,
  1746.                             REFRESHWINDOW|MENUPICK);
  1747.                     SetMenuStrip(intwindow, &menu0);
  1748.                     SetWindowTitles(intwindow, NULL, (UBYTE *) title);
  1749.                     ReplyMsg(msg);
  1750.                     break;
  1751.  
  1752.                 /* Close the windows and tidy up */
  1753.  
  1754.                 case PSACTCLOSE:
  1755.                     ClearMenuStrip(intwindow);
  1756.                     ModifyIDCMP(bitwindow, CLOSEWINDOW);
  1757.                     ModifyIDCMP(intwindow, CLOSEWINDOW);
  1758.                     bitwindow->UserPort = NULL;
  1759.                     intwindow->UserPort = NULL;
  1760.                     for (;;)
  1761.                     {   msg = GetMsg(menuport);
  1762.                         if (msg == NULL) break;
  1763.                         ReplyMsg(msg);
  1764.                     }
  1765.                     DeletePort(menuport);
  1766.                     menuport = NULL;
  1767.                     goto end;
  1768.  
  1769.                 /* Flush the bitmap to its window */
  1770.  
  1771.                 case PSACTFLUSH:
  1772.                     i = menumsg.y1;
  1773.                     j = menumsg.y2;
  1774.                     if (i < winypos) i = winypos;
  1775.                     if (j < winypos) j = winypos;
  1776.                     if (i > winypos + winysize) i = winypos + winysize;
  1777.                     if (j > winypos + winysize) j = winypos + winysize;
  1778.                     if (j > i && argscreen)
  1779.                     {   BltBitMapRastPort(&bitmap, winxpos, i,
  1780.                                           bitwindow->RPort,
  1781.                                           winxbase, winybase + i - winypos,
  1782.                                           winxsize, j - i, 0xC0);
  1783.                     }
  1784.                     ReplyMsg(msg);
  1785.                     break;
  1786.  
  1787.                 /* Pause at the end of a page */
  1788.  
  1789.                 case PSACTPAUSE:
  1790.                     if (pause)
  1791.                     {   savetitle = title;
  1792.                         title = titlepaused;
  1793.                         SetWindowTitles(intwindow, NULL, (UBYTE *) title);
  1794.                         OnMenu(intwindow, 2 | SHIFTITEM(1));
  1795.                     }
  1796.                     else
  1797.                         ReplyMsg(msg);
  1798.                     break;
  1799.  
  1800.                 /* Get the next command */
  1801.  
  1802.                 case PSACTCOMMAND:
  1803.                     title = titlewait;
  1804.                     SetWindowTitles(intwindow, NULL, (UBYTE *) title);
  1805.                     OnMenu(intwindow, 0 | SHIFTITEM(NOITEM));
  1806.                     OnMenu(intwindow, 1 | SHIFTITEM(NOITEM));
  1807.                     break;
  1808.  
  1809.                 /* Get a quit or restart command */
  1810.  
  1811.                 case PSACTEXIT:
  1812.                     title = titlewait;
  1813.                     SetWindowTitles(intwindow, NULL, (UBYTE *) title);
  1814.                     OnMenu(intwindow, 0 | SHIFTITEM(NOITEM));
  1815.                     OffMenu(intwindow, 2 | SHIFTITEM(NOITEM));
  1816.                     break;
  1817.             }
  1818.         }
  1819.  
  1820.         /* Message from Intuition */
  1821.  
  1822.         else
  1823.         {   switch (((struct IntuiMessage *) msg)->Class)
  1824.             {
  1825.                 /* Make the interactive window the active one */
  1826.  
  1827.                 case ACTIVEWINDOW:
  1828.                     ActivateWindow(intwindow);
  1829.                     break;
  1830.  
  1831.                 /* Refresh a window */
  1832.  
  1833.                 case REFRESHWINDOW:
  1834.  
  1835.                     /* Refresh the bitmapped window */
  1836.  
  1837.                     if (((struct IntuiMessage *)msg)->IDCMPWindow ==
  1838.                                                                  bitwindow)
  1839.                     {   BeginRefresh(bitwindow);
  1840.                         if (argscreen)
  1841.                             BltBitMapRastPort(&bitmap, winxpos, winypos,
  1842.                                               bitwindow->RPort,
  1843.                                               winxbase, winybase,
  1844.                                               winxsize, winysize, 0xC0);
  1845.                         EndRefresh(bitwindow, TRUE);
  1846.                     }
  1847.  
  1848.                     /* We don't actually refresh the interactive window, but
  1849.                      * instead we use this event to tell us when it has
  1850.                      * changed size, so we can adjust the size and position
  1851.                      * of the bitmapped window to match.  (Despite what the
  1852.                      * manual says we seem to get the refresh message even
  1853.                      * when the window gets smaller */
  1854.  
  1855.                     else
  1856.                     {   i = intwindow->Height;
  1857.                         j = i - height;
  1858.                         height = i;
  1859.                         if      (j < 0)
  1860.                         {   MoveWindow(bitwindow, 0, j);
  1861.                             SizeWindow(bitwindow, 0, -j);
  1862.                         }
  1863.                         else if (j > 0)
  1864.                         {   SizeWindow(bitwindow, 0, -j);
  1865.                             MoveWindow(bitwindow, 0, j);
  1866.                         }
  1867.                         winypos += j;
  1868.                         if (winypos < 0) winypos = 0;
  1869.                         winysize -= j;
  1870.                         ModifyProp(&vscrollgadg, bitwindow, NULL,
  1871.                             AUTOKNOB|FREEVERT,
  1872.                             -1, (0xffff * winypos) /
  1873.                                     (parm.page.ysize - winysize),
  1874.                             -1, (0xffff * winysize) / parm.page.ysize);
  1875.                     }
  1876.  
  1877.                     break;
  1878.  
  1879.                 /* Scroll the bitmapped window.  Make sure we can scroll to
  1880.                  * the edges of the page, even after rounding erors */
  1881.  
  1882.                 case GADGETUP:
  1883.                     ActivateWindow(intwindow);
  1884.                     if      (((struct IntuiMessage *) msg)->IAddress ==
  1885.                                     (APTR) &hscrollgadg)
  1886.                     {   i = (parm.page.xsize - winxsize);
  1887.                         j = (i * hscrollinfo.HorizPot) / 65535;
  1888.                         if (j < i / 30) j = 0;
  1889.                         if (i - j < i / 30) j = i;
  1890.                         winxpos = j;
  1891.                     }
  1892.                     else if (((struct IntuiMessage *) msg)->IAddress ==
  1893.                                     (APTR) &vscrollgadg)
  1894.                     {   i = (parm.page.ysize - winysize);
  1895.                         j = (i * vscrollinfo.VertPot) / 65535;
  1896.                         if (j < i / 30) j = 0;
  1897.                         if (i - j < i / 30) j = i;
  1898.                         winypos = j;
  1899.                     }
  1900.                     if (argscreen)
  1901.                         BltBitMapRastPort(&bitmap, winxpos, winypos,
  1902.                                           bitwindow->RPort,
  1903.                                           winxbase, winybase,
  1904.                                           winxsize, winysize, 0xC0);
  1905.                     break;
  1906.  
  1907.                 /* Menu selection.  We don't implement extended selection
  1908.                  * to avoid real time problems, and it wouldn't be useful
  1909.                  * for our range of choices anyway */
  1910.  
  1911.                 case MENUPICK:
  1912.                     i = ((struct IntuiMessage *) msg)->Code;
  1913.                     j = ITEMNUM(i);
  1914.                     i = MENUNUM(i);
  1915.                     oldtitle = title;
  1916.                     if      (i == 0)     /* Project */
  1917.                     {   if      (j == 0) /*   Restart */
  1918.                             menumsg.command = PSCOMRESTART;
  1919.                         else if (j == 1) /*   Quit */
  1920.                             menumsg.command = PSCOMQUIT;
  1921.                     }
  1922.                     else if (i == 1)     /* File */
  1923.                     {   title = titlerunning;
  1924.                         if      (j == 0) /*   Load font */
  1925.                             menumsg.command = PSCOMFILEF;
  1926.                         else if (j == 1) /*   Load file */
  1927.                             menumsg.command = PSCOMFILEL;
  1928.                         else if (j == 2) /*   Run file */
  1929.                             menumsg.command = PSCOMFILER;
  1930.                         else if (j == 3) /*   Interactive */
  1931.                         {   menumsg.command = PSCOMINTER;
  1932.                             title = titleinter;
  1933.                         }
  1934.                     }
  1935.                     else if (i == 2)     /* Control */
  1936.                     {   if      (j == 0) /*   Pause every page */
  1937.                         {   pause = !pause;
  1938.                             if (pause)
  1939.                                 men2item0.Flags |=  CHECKED;
  1940.                             else
  1941.                                 men2item0.Flags &= ~CHECKED;
  1942.                             break;
  1943.                         }
  1944.                         else if (j == 1) /*   Continue after pause */
  1945.                         {   menumsg.command = 0;
  1946.                             title = savetitle;
  1947.                             OffMenu(intwindow, 2 | SHIFTITEM(1));
  1948.                         }
  1949.                         else if (j == 2) /*   Interrupt */
  1950.                         {   PSsignalint(arec, 1);
  1951.                             break;
  1952.                         }
  1953.                     }
  1954.                     else                 /* NULL */
  1955.                         break;
  1956.                     OffMenu(intwindow, 0 | SHIFTITEM(NOITEM));
  1957.                     OffMenu(intwindow, 1 | SHIFTITEM(NOITEM));
  1958.                     if (title != oldtitle)
  1959.                         SetWindowTitles(intwindow, NULL, (UBYTE *) title);
  1960.                     menumsg.length = -1;
  1961.                     menumsg.string = NULL;
  1962.                     ReplyMsg((struct Message *) &menumsg);
  1963.                     break;
  1964.             }
  1965.             ReplyMsg(msg);
  1966.         }
  1967.  
  1968.         /* Get next message */
  1969.  
  1970.         for (;;)
  1971.         {   msg = GetMsg(menuport);
  1972.             if (msg) break;
  1973.             WaitPort(menuport);
  1974.         }
  1975.     }
  1976.  
  1977.     /* Open failure or close.  Reply remove our task */
  1978.  
  1979. end:
  1980.     Forbid();
  1981.     ReplyMsg((struct Message *) &menumsg);
  1982.     menutask = NULL;
  1983.     RemTask(menutask);
  1984. }
  1985.  
  1986. /* Signal an interrupt */
  1987.  
  1988. void __saveds sigint()
  1989. {   PSsignalint(arec, 1);
  1990. }
  1991.  
  1992. /* Signal a floating point error */
  1993.  
  1994. void __saveds sigfpe()
  1995. {   PSsignalfpe(arec);
  1996. }
  1997.  
  1998. /* Flush the page to the screen */
  1999.  
  2000. # ifdef STATICLINK
  2001. void flushpage(int y1, int y2)
  2002. # else
  2003. void __saveds __asm flushpage(register __d0 int y1, register __d1 int y2)
  2004. # endif
  2005. {   if (argscreen)
  2006.     {   menumsg.y1 = y1;
  2007.         menumsg.y2 = y2;
  2008.         sendmenu(PSACTFLUSH);
  2009.     }
  2010. }
  2011.  
  2012. /* Copy the page to the output */
  2013.  
  2014. # ifdef STATICLINK
  2015. void copypage(int num)
  2016. # else
  2017. void __saveds __asm copypage(register __d0 int num)
  2018. # endif
  2019. {   ioerror = 0;
  2020.     if (argprint)
  2021.         while (num--) printpage();
  2022.     if (argiff)
  2023.         iffpage();
  2024.     if (argscreen)
  2025.         sendmenu(PSACTPAUSE);
  2026.     if (ioerror) PSerror(arec, ioerror);
  2027. }
  2028.  
  2029. /* Print the page */
  2030.  
  2031. void printpage()
  2032. {   ULONG sig;
  2033.  
  2034.     /* Disable break exceptions so we can wait on the signal instead */
  2035.  
  2036.     SetExcept(0, SIGBREAKF_CTRL_C);
  2037.     breakset = 0;
  2038.  
  2039.     /* First check the printer is ready */
  2040.  
  2041.     prreq.io_Command = PRD_QUERY;
  2042.     ((struct IOStdReq *) &prreq)->io_Data = (APTR) prstatus;
  2043.     if (DoIO((struct IORequest *) &prreq))
  2044.     {   ioerror = errioerror;
  2045.         return;
  2046.     }
  2047.     if (((struct IOStdReq *) &prreq)->io_Actual == 1 && prstatus[0] & 3 != 0)
  2048.         FPrintf(argint ? confh : errfh,
  2049.                 "post: printer not ready (CTRL/C to abort)\n");
  2050.  
  2051.     /* Now dump the page */
  2052.  
  2053.     prrast.BitMap = &bitmap;
  2054.     prreq.io_Command = PRD_DUMPRPORT;
  2055.     prreq.io_RastPort = &prrast;
  2056.     prreq.io_ColorMap = (struct ColorMap *) &colormap;
  2057.     prreq.io_Modes = 0;
  2058.     prreq.io_SrcX = 0;
  2059.     prreq.io_SrcY = 0;
  2060.     prreq.io_SrcWidth = parm.page.xsize;
  2061.     prreq.io_SrcHeight = parm.page.ysize;
  2062.     prreq.io_DestCols = parm.page.xsize;
  2063.     prreq.io_DestRows = parm.page.ysize;
  2064.     prreq.io_Special = (SPECIAL_DENSITY1 * prden) | SPECIAL_TRUSTME;
  2065.     if (parm.page.ybase + parm.page.ysize >= parm.page.yheight)
  2066.         prreq.io_SrcHeight = prreq.io_DestRows =
  2067.                 parm.page.yheight - parm.page.ybase;
  2068.     else
  2069.         prreq.io_Special |= SPECIAL_NOFORMFEED;
  2070.  
  2071.     /* We use asynchronous IO so we can abort it with a CTRL/C */
  2072.  
  2073.     SendIO((struct IORequest *) &prreq);
  2074.  
  2075.     for (;;)
  2076.     {   sig = Wait(prsig | SIGBREAKF_CTRL_C);
  2077.         if (sig & SIGBREAKF_CTRL_C)
  2078.         {   AbortIO((struct IORequest *) &prreq);
  2079.             WaitIO((struct IORequest *) &prreq);
  2080.             ioerror = errioerror;
  2081.             break;
  2082.         }
  2083.         if (sig & prsig)
  2084.         {   GetMsg(prport);
  2085.             break;
  2086.         }
  2087.     }
  2088.     if (prreq.io_Error != 0) ioerror = errioerror;
  2089.  
  2090.     /* Restore break exceptions */
  2091.  
  2092.     SetExcept(~0, SIGBREAKF_CTRL_C);
  2093.     breakset = 1;
  2094. }
  2095.  
  2096. /* IFF ILBM routines */
  2097.  
  2098. static int iffseq = 0;
  2099.  
  2100. static int ifferr;
  2101.  
  2102. static FILE *ifffptr;
  2103.  
  2104. /* Put a byte */
  2105.  
  2106. static void iffputb(int b)
  2107. {   if (ifferr) return;
  2108.     if (putc((int) b, ifffptr) == EOF)
  2109.     {   ifferr = 1;
  2110.         return;
  2111.     }
  2112. }
  2113.  
  2114. /* Put a word */
  2115.  
  2116. static void iffputw(int w)
  2117. {   iffputb(w>>8);
  2118.     iffputb(w);
  2119. }
  2120.  
  2121. /* Put a long */
  2122.  
  2123. static void iffputl(int l)
  2124. {   iffputb(l>>24);
  2125.     iffputb(l>>16);
  2126.     iffputb(l>>8);
  2127.     iffputb(l);
  2128. }
  2129.  
  2130. /* Put a string */
  2131.  
  2132. static void iffputs(char *str)
  2133. {   while (*str) iffputb(*str++);
  2134. }
  2135.  
  2136. /* Pack a bitmap row */
  2137.  
  2138. static void iffpack(char *buf, int len)
  2139. {   int b, c, l;
  2140.     if (ifferr) return;
  2141.     l = 0;
  2142.     while (len--)
  2143.     {   b = *buf++;                  /* Pick up a byte */
  2144.         c = 1;
  2145.         while (len && *buf == b && c < 128)
  2146.         {   c++;
  2147.             buf++;
  2148.             len--;                   /* See if it begins a run */
  2149.         }
  2150.         if (c == 2 &&                /* If a two byte run */
  2151.             l > 0 &&                 /*    and preceeded by literals */
  2152.             l <= 125 &&              /*    and not more than 125 of them */
  2153.             (len <= 2 ||             /*    and no more than 2 bytes left */
  2154.              *buf != *(buf + 1)))    /*        or not followed by a run */
  2155.         {   c = 1;                   /* Then make it a literal */
  2156.             buf--;
  2157.             len++;
  2158.         }
  2159.         if (c == 1)                  /* If not a run */
  2160.         {   l++;                     /* Then it must be a literal */
  2161.             c = 0;
  2162.         }
  2163.         if (l > 0 &&                 /* If we have some literals */
  2164.             (c > 1 ||                /*    and beginning a run */
  2165.              l == 127 ||             /*    or reached 127 */
  2166.              len == 0))              /*    or no more bytes left */
  2167.         {   if (putc(l - 1, ifffptr) == EOF)
  2168.             {   ifferr = 1;
  2169.                 return;
  2170.             }
  2171.             while (l)              /* Then write out  the literals */
  2172.             {   if (putc(*(buf - c - l), ifffptr) == EOF)
  2173.                 {   ifferr = 1;
  2174.                     return;
  2175.                 }
  2176.                 l--;
  2177.             }
  2178.         }
  2179.         if (c > 1)                   /* If we have a run, write it */
  2180.         {   if (putc(1 - c, ifffptr) == EOF)
  2181.             {   ifferr = 1;
  2182.                 return;
  2183.             }
  2184.             if (putc(b, ifffptr) == EOF)
  2185.             {   ifferr = 1;
  2186.                 return;
  2187.             }
  2188.         }
  2189.     }
  2190. }
  2191.  
  2192. /* Determine the current address */
  2193.  
  2194. static long ifftell(void)
  2195. {   long addr;
  2196.     if (ifferr) return 0;
  2197.     if ((addr = ftell(ifffptr)) == -1)
  2198.     {   ifferr = 1;
  2199.         return 0;
  2200.     }
  2201.     return addr;
  2202. }
  2203.  
  2204. /* Fix up the length of a chunk */
  2205.  
  2206. static void ifffixup(long addr)
  2207. {   long size;
  2208.     if (ifferr) return;
  2209.     if ((size = ftell(ifffptr)) == -1)
  2210.     {   ifferr = 1;
  2211.         return;
  2212.     }
  2213.     if (size & 1) iffputb(0);
  2214.     size = size - addr - 8;
  2215.     if (fseek(ifffptr, addr + 4, 0) != 0)
  2216.     {   ifferr = 1;
  2217.         return;
  2218.     }
  2219.     iffputl(size);
  2220.     if (fseek(ifffptr, 0, 2) != 0)
  2221.     {   ifferr = 1;
  2222.         return;
  2223.     }
  2224. }
  2225.  
  2226. /* Write the page to the iff output file */
  2227.  
  2228. void iffpage(void)
  2229. {   long addr1, addr2;
  2230.     int xa, ya;
  2231.     int i, j, k, ch;
  2232.     UWORD w;
  2233.     int fslen;
  2234.     char fname[110], fsnum[10];
  2235.  
  2236.     /* Compute the aspect ratio.  Make sure the values fit into a byte */
  2237.  
  2238.     xa = parm.page.yden;
  2239.     ya = parm.page.xden;
  2240.     i = igcd(xa, ya);
  2241.     xa /= i;
  2242.     ya /= i;
  2243.     while (xa > 255 && ya > 255)
  2244.     {   xa /= 2;
  2245.         ya /= 2;
  2246.     }
  2247.  
  2248.     /* Construct the file name.  Copy it, replacing "*" by the sequence
  2249.      * number.  The scan it backwards replacing "?" by digits */
  2250.  
  2251.     iffseq++;
  2252.     fslen = 0;
  2253.     i = iffseq;
  2254.     while (i)
  2255.     {   fsnum[fslen++] = i % 10 + '0';
  2256.         i /= 10;
  2257.     }
  2258.     i = j = 0;
  2259.     for (;;)
  2260.     {   if (j > 100)
  2261.         {   ioerror = errioerror;
  2262.             return;
  2263.         }
  2264.         ch = argifn[i++];
  2265.         if (ch == '*')
  2266.         {   k = fslen;
  2267.             while (k--) fname[j++] = fsnum[k];
  2268.         }
  2269.         else
  2270.            fname[j++] = ch;
  2271.         if (ch == 0) break;
  2272.     }
  2273.     k = 0;
  2274.     while (--j)
  2275.     {   if (fname[j] == '?')
  2276.             fname[j] = (k < fslen) ? fsnum[k++] : '0';
  2277.     }
  2278.  
  2279.     /* Open the file, write a FORM ILBM, and close it again */
  2280.  
  2281.     ifferr = 0;
  2282.     ifffptr = fopen(fname, "wb");
  2283.     if (ifffptr == NULL) ifferr = 1;
  2284.  
  2285.     addr1 = ifftell();
  2286.     iffputs("FORM");          /* FORM ILBM */
  2287.     iffputl(0);
  2288.     iffputs("ILBM");
  2289.  
  2290.     iffputs("BMHD");          /* BMHD */
  2291.     iffputl(20);
  2292.     iffputw(parm.page.xsize); /* Width */
  2293.     iffputw(parm.page.ysize); /* Height */
  2294.     iffputw(0);               /* X position */
  2295.     iffputw(0);               /* Y position */
  2296.     iffputb(parm.page.depth); /* Number of bit planes */
  2297.     iffputb(0);               /* Masking:     None */
  2298.     iffputb(1);               /* Compression: ByteRun */
  2299.     iffputb(0);               /* Pad1 */
  2300.     iffputw(0);               /* Transparent colour */
  2301.     iffputb(xa);              /* X aspect */
  2302.     iffputb(ya);              /* Y aspect */
  2303.     iffputw(parm.page.xsize); /* Source width */
  2304.     iffputw(parm.page.ysize); /* Source height */
  2305.  
  2306.     addr2 = ifftell();
  2307.     iffputs("CMAP");          /* CMAP */
  2308.     iffputl(0);
  2309.     for (i = 0; i < colormap.Count; i++)
  2310.     {   w = ((UWORD *) colormap.ColorTable)[i];
  2311.         iffputb(((w >> 8) & 15) << 4);
  2312.         iffputb(((w >> 4) & 15) << 4);
  2313.         iffputb(( w       & 15) << 4);
  2314.     }
  2315.     ifffixup(addr2);
  2316.  
  2317.     if (argscreen)
  2318.     {   iffputs("CAMG");      /* CAMG */
  2319.         iffputl(4);
  2320.         iffputl(newscreen.ViewModes);
  2321.     }
  2322.  
  2323.     addr2 = ifftell();
  2324.     iffputs("BODY");          /* BODY */
  2325.     iffputl(0);
  2326.     for (j = 0; j < bitmap.Rows; j++)
  2327.         for (i = 0; i < bitmap.Depth; i++)
  2328.             iffpack((char *) bitmap.Planes[i] + j * bitmap.BytesPerRow,
  2329.                     bitmap.BytesPerRow);
  2330.     ifffixup(addr2);
  2331.  
  2332.     ifffixup(addr1);
  2333.  
  2334.     if (fclose(ifffptr) == EOF)
  2335.         ifferr = 1;
  2336.     if (ifferr) ioerror = errioerror;
  2337. }
  2338.  
  2339. /* Find the greatest common divisor of two positive integers.  If one is
  2340.  * zero the result is the other */
  2341.  
  2342. int igcd(int n, int m)
  2343. {   unsigned int n1, m1, r;
  2344.     if      (n > m)
  2345.     {   n1 = n;
  2346.         m1 = m;
  2347.     }
  2348.     else if (m > n)
  2349.     {   n1 = m;
  2350.         m1 = n;
  2351.     }
  2352.     else
  2353.         return n;
  2354.     while (m1 != 0)
  2355.     {   r = n1 % m1;
  2356.         n1 = m1;
  2357.         m1 = r;
  2358.     }
  2359.     return (int) n1;
  2360. }
  2361.  
  2362. /* End of file "post.c" */
  2363.