/* PostScript interpreter file "post.c" - the main program (Amiga) * (C) Adrian Aylward 1989, 1991 * * This file contains the code to parse the command line arguments, the * WorkBench and intuition interface, and the printer screen or IFF file] * output routines. It is therfore heavily Amiga dependent. It calls the * interpreter library for all the PostScript stuff. * * There are also various Lattice dependencies: the startup code in _main, * the menu task, the flush and copy functions, and the floating point trap * and break handling. */ # include # include # include # include # include # include # include # include # include # include # include # include # include # include # include # include # include # include # include # include # include # include # include "postlib.h" /* Assembler routines */ extern void insertbreak(void); extern void deletebreak(void); extern void insertftrap(void); extern void deleteftrap(void); /* Routines defined and referenced only within this module */ extern void errmsg(char *string); extern void tidyup(void); extern void setprinter(void); extern void setprintden(void); extern void setreqgadgets(void); extern void getreqgadgets(void); extern void enablegadg(struct Gadget *gadget, int enable); extern void setgadgbool(struct Gadget *gadget, int value); extern int getgadgbool(struct Gadget *gadget); extern void setgadgint(struct Gadget *gadget, int value); extern int getgadgint(struct Gadget *gadget); extern int getgadgabs(struct Gadget *gadget); extern int strtoint(char **sp, int *ip); extern void sendmenu(int action); extern void __saveds menuproc(void); # ifndef STATICLINK extern void __saveds __asm flushpage(register __d0 int y1, register __d1 int y2); extern void __saveds __asm copypage(register __d0 int num); # endif extern void printpage(void); extern void iffpage(void); extern int igcd(int n, int m); /* Message structure */ struct PSmessage { struct Message ExecMessage; long class; /* Always zero */ short action; /* Action - from Post to handler */ short command; /* Command - from handler to Post */ struct BitMap *bitmap; /* The bitmap */ short y1, y2; /* Min and max+1 y values to flush */ short result; /* Result (return code) */ short length; /* Length of string */ char *string; /* String */ long window; /* Always zero */ short errnum; /* Last error number */ short zero; /* Reserved, presently always zero */ }; /* Actions */ # define PSACTOPEN 1 /* Open */ # define PSACTCLOSE 2 /* Close */ # define PSACTFLUSH 3 /* Flush out the bitmap */ # define PSACTPAUSE 4 /* Pause at the end of a page */ # define PSACTCOMMAND 5 /* Get a command */ # define PSACTEXIT 6 /* Exit */ /* Commands */ # define PSCOMQUIT 1 /* Quit */ # define PSCOMRESTART 2 /* Restart */ # define PSCOMFILEF 3 /* Load Font */ # define PSCOMFILEL 4 /* Load File */ # define PSCOMFILER 5 /* Run File */ # define PSCOMINTER 6 /* Interactive */ /* Lattice startup */ extern struct WBStartup *WBenchMsg; /* External data (initialised to zero) */ int retcode, errcode, ioerror; int fatalerror, restarterror, requested; int arec; BPTR errfh, confh; # ifndef STATICLINK struct library *PSbase; # endif struct PSparm parm; struct PSmessage menumsg; struct ArpBase *ArpBase; struct FileRequester *filereq, *filereq1, *filereq2; struct Process *process; struct MsgPort *mainport, *menuport; struct Task *menutask; struct Screen *screen; struct Window *syswindow, *reqwindow, *errwindow, *bitwindow, *intwindow; struct BitMap bitmap; struct ColorMap colormap; struct TextFont *textfont; int propen, prden; struct IODRPReq prreq; struct PrinterData *prdata; struct PrinterExtendedData *prextdata; struct Preferences *prprefs; struct RastPort prrast; struct MsgPort *prport; ULONG prsig; UBYTE prstatus[2]; int breakset, ftrapset; int winxbase, winybase, winxsize, winysize, winxpos, winypos; /* Colour tables. The default color map type is a vector or UWORD RGB * values. The colours are inverted as we set a bit in the bitmap whenever * we want to place a drop of (black or cyan/magenta/yellow) ink */ static UWORD bcolors[2] = /* Black and white */ { 0xfff, 0x000 /* White black */ }; static UWORD ccolors[16] = /* Colour (RGB or CMYK) */ { 0xfff, 0x0ff, 0xf0f, 0x00f, /* White cyan magenta blue */ 0xff0, 0x0f0, 0xf00, 0x000, /* Yellow green red black */ 0x000, 0x000, 0x000, 0x000, /* Black */ 0x000, 0x000, 0x000, 0x000 /* Black */ }; char titlewait[] = POSTVER " Copyright Adrian Aylward 1989, 1991"; char titlestart[] = POSTVER " Running startup file(s)"; char titlerunning[] = POSTVER " Running"; char titleinter[] = POSTVER " Interactive"; char titlepaused[] = POSTVER " Paused"; char hailfilef[] = POSTVER " Select font to load"; char hailfilen[] = POSTVER " Select file to load"; char hailfiles[] = POSTVER " Select file to run"; /* The default font and screen */ struct TextAttr topaz11 = /* Font is Topaz 11 */ { "topaz.font", 11, FS_NORMAL, FPF_DISKFONT }; struct NewScreen newscreen = /* Screen */ { 0, 0, 640, 512, 1, 0, 15, LACE|HIRES, CUSTOMSCREEN, &topaz11, (UBYTE *) &titlewait, NULL, NULL }; /* Stuff for the options requestor */ # define GADGOK 1 /* Gadget id's */ # define GADGCAN 2 # define GADGPRI 3 # define GADGBW 4 # define GADGC3 5 # define GADGC4 6 # define GADGPD1 7 # define GADGPD2 8 # define GADGPD3 9 # define GADGPD4 10 # define GADGPD5 11 # define GADGPD6 12 # define GADGPD7 13 # define GADGABS 14 /* Integer gadget, absolute value */ # define GADGRST 15 /* Dummy gadget to restart after error */ char undobuff[80]; SHORT bordervec1[] = { 0, 0, 67, 0, 67, 14, 0, 14, 0, 1 }; struct Border border1 = { -2, -2, 15, 0, JAM1, 5, bordervec1, NULL }; UBYTE mlgadgbuff[8]; struct StringInfo mlgadginfo = { mlgadgbuff, (UBYTE *)undobuff, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, NULL }; struct Gadget mlgadg = { NULL, 500, 212, 64, 13, 0, STRINGRIGHT|LONGINT|RELVERIFY, STRGADGET, (APTR)&border1, NULL, NULL, 0, (APTR)&mlgadginfo, GADGABS, NULL }; UBYTE mvgadgbuff[8]; struct StringInfo mvgadginfo = { mvgadgbuff, (UBYTE *)undobuff, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, NULL }; struct Gadget mvgadg = { &mlgadg, 500, 198, 64, 13, 0, STRINGRIGHT|LONGINT|RELVERIFY, STRGADGET, (APTR)&border1, NULL, NULL, 0, (APTR)&mvgadginfo, GADGABS, NULL }; UBYTE mhgadgbuff[8]; struct StringInfo mhgadginfo = { mhgadgbuff, (UBYTE *)undobuff, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, NULL }; struct Gadget mhgadg = { &mvgadg, 500, 184, 64, 13, 0, STRINGRIGHT|LONGINT|RELVERIFY, STRGADGET, (APTR)&border1, NULL, NULL, 0, (APTR)&mhgadginfo, GADGABS, NULL }; UBYTE mfgadgbuff[8]; struct StringInfo mfgadginfo = { mfgadgbuff, (UBYTE *)undobuff, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, NULL }; struct Gadget mfgadg = { &mhgadg, 500, 170, 64, 13, 0, STRINGRIGHT|LONGINT|RELVERIFY, STRGADGET, (APTR)&border1, NULL, NULL, 0, (APTR)&mfgadginfo, GADGABS, NULL }; SHORT bordervec2[] = { 0, 0, 43, 0, 43, 14, 0, 14, 0, 1 }; struct Border border2 = { -2, -2, 15, 0, JAM1, 5, bordervec2, NULL }; UBYTE ydgadgbuff[5]; struct StringInfo ydgadginfo = { ydgadgbuff, (UBYTE *)undobuff, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, NULL }; struct Gadget ydgadg = { &mfgadg, 388, 198, 40, 13, 0, STRINGRIGHT|LONGINT|RELVERIFY, STRGADGET, (APTR)&border2, NULL, NULL, 0, (APTR)&ydgadginfo, GADGABS, NULL }; UBYTE xdgadgbuff[5]; struct StringInfo xdgadginfo = { xdgadgbuff, (UBYTE *)undobuff, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, NULL }; struct Gadget xdgadg = { &ydgadg, 345, 198, 40, 13, 0, STRINGRIGHT|LONGINT|RELVERIFY, STRGADGET, (APTR)&border2, NULL, NULL, 0, (APTR)&xdgadginfo, GADGABS, NULL }; UBYTE yogadgbuff[5]; struct StringInfo yogadginfo = { yogadgbuff, (UBYTE *)undobuff, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, NULL }; struct Gadget yogadg = { &xdgadg, 388, 184, 40, 13, 0, STRINGRIGHT|LONGINT, STRGADGET, (APTR)&border2, NULL, NULL, 0, (APTR)&yogadginfo, 0, NULL }; UBYTE xogadgbuff[5]; struct StringInfo xogadginfo = { xogadgbuff, (UBYTE *)undobuff, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, NULL }; struct Gadget xogadg = { &yogadg, 345, 184, 40, 13, 0, STRINGRIGHT|LONGINT, STRGADGET, (APTR)&border2, NULL, NULL, 0, (APTR)&xogadginfo, 0, NULL }; UBYTE ygadgbuff[5]; struct StringInfo ygadginfo = { ygadgbuff, (UBYTE *)undobuff, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, NULL }; struct Gadget ygadg = { &xogadg, 388, 170, 40, 13, 0, STRINGRIGHT|LONGINT|RELVERIFY, STRGADGET, (APTR)&border2, NULL, NULL, 0, (APTR)&ygadginfo, GADGABS, NULL }; UBYTE xgadgbuff[5]; struct StringInfo xgadginfo = { xgadgbuff, (UBYTE *)undobuff, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, NULL }; struct Gadget xgadg = { &ygadg, 345, 170, 40, 13, 0, STRINGRIGHT|LONGINT|RELVERIFY, STRGADGET, (APTR)&border2, NULL, NULL, 0, (APTR)&xgadginfo, GADGABS, NULL }; short __chip idata1[] = { 0xfffe, 0x8002, 0x8002, 0x8002, 0x8002, 0x8002, 0x8002, 0x8002, 0x8002, 0x8002, 0x8002, 0x8002, 0x8002, 0x8002, 0xfffe, 0xfffe, 0x8002, 0x8002, 0x8002, 0x8002, 0x8002, 0x8002, 0x8002, 0x8002, 0x8002, 0x8002, 0x8002, 0x8002, 0x8002, 0xfffe, 0xfffe, 0x8002, 0x8002, 0x8002, 0x8002, 0x8002, 0x8002, 0x8002, 0x8002, 0x8002, 0x8002, 0x8002, 0x8002, 0x8002, 0xfffe, 0xfffe, 0x8002, 0x8002, 0x8002, 0x8002, 0x8002, 0x8002, 0x8002, 0x8002, 0x8002, 0x8002, 0x8002, 0x8002, 0x8002, 0xfffe }; struct Image image1 = { -2, -2, 15, 15, 4, &idata1[0], 15, 0, NULL }; struct IntuiText itext30 = { 15, 0, JAM2, 1, 1, NULL, "7", NULL }; struct IntuiText itext29 = { 15, 0, JAM2, 1, 1, NULL, "6", NULL }; struct IntuiText itext28 = { 15, 0, JAM2, 1, 1, NULL, "5", NULL }; struct IntuiText itext27 = { 15, 0, JAM2, 1, 1, NULL, "4", NULL }; struct IntuiText itext26 = { 15, 0, JAM2, 1, 1, NULL, "3", NULL }; struct IntuiText itext25 = { 15, 0, JAM2, 1, 1, NULL, "2", NULL }; struct IntuiText itext24 = { 15, 0, JAM2, 1, 1, NULL, "1", NULL }; struct Gadget pd7gadg = { &xgadg, 526, 114, 11, 11, GADGIMAGE, RELVERIFY, BOOLGADGET, (APTR)&image1, NULL, &itext30, 0, NULL, GADGPD7, NULL }; struct Gadget pd6gadg = { &pd7gadg, 512, 114, 11, 11, GADGIMAGE, RELVERIFY, BOOLGADGET, (APTR)&image1, NULL, &itext29, 0, NULL, GADGPD6, NULL }; struct Gadget pd5gadg = { &pd6gadg, 498, 114, 11, 11, GADGIMAGE, RELVERIFY, BOOLGADGET, (APTR)&image1, NULL, &itext28, 0, NULL, GADGPD5, NULL }; struct Gadget pd4gadg = { &pd5gadg, 484, 114, 11, 11, GADGIMAGE, RELVERIFY, BOOLGADGET, (APTR)&image1, NULL, &itext27, 0, NULL, GADGPD4, NULL }; struct Gadget pd3gadg = { &pd4gadg, 470, 114, 11, 11, GADGIMAGE, RELVERIFY, BOOLGADGET, (APTR)&image1, NULL, &itext26, 0, NULL, GADGPD3, NULL }; struct Gadget pd2gadg = { &pd3gadg, 456, 114, 11, 11, GADGIMAGE, RELVERIFY, BOOLGADGET, (APTR)&image1, NULL, &itext25, 0, NULL, GADGPD2, NULL }; struct Gadget pd1gadg = { &pd2gadg, 442, 114, 11, 11, GADGIMAGE, RELVERIFY, BOOLGADGET, (APTR)&image1, NULL, &itext24, 0, NULL, GADGPD1, NULL }; struct Gadget cwbgadg = { &pd1gadg, 417, 226, 11, 11, GADGIMAGE, TOGGLESELECT, BOOLGADGET, (APTR)&image1, NULL, NULL, 0, NULL, 0, NULL }; struct Gadget c4gadg = { &cwbgadg, 553, 86, 11, 11, GADGIMAGE, RELVERIFY, BOOLGADGET, (APTR)&image1, NULL, NULL, 0, NULL, GADGC4, NULL }; struct Gadget c3gadg = { &c4gadg, 553, 72, 11, 11, GADGIMAGE, RELVERIFY, BOOLGADGET, (APTR)&image1, NULL, NULL, 0, NULL, GADGC3, NULL }; struct Gadget bwgadg = { &c3gadg, 553, 58, 11, 11, GADGIMAGE, RELVERIFY, BOOLGADGET, (APTR)&image1, NULL, NULL, 0, NULL, GADGBW, NULL }; struct Gadget iffgadg = { &bwgadg, 382, 86, 11, 11, GADGIMAGE, TOGGLESELECT, BOOLGADGET, (APTR)&image1, NULL, NULL, 0, NULL, 0, NULL }; struct Gadget scrgadg = { &iffgadg, 382, 72, 11, 11, GADGIMAGE, TOGGLESELECT, BOOLGADGET, (APTR)&image1, NULL, NULL, 0, NULL, 0, NULL }; struct Gadget prigadg = { &scrgadg, 382, 58, 11, 11, GADGIMAGE, TOGGLESELECT|RELVERIFY, BOOLGADGET, (APTR)&image1, NULL, NULL, 0, NULL, GADGPRI, NULL }; SHORT bordervec3[] = { 0, 0, 101, 0, 101, 33, 0, 33, 0, 1 }; struct Border border3 = { -1, -1, 15, 0, JAM1, 5, bordervec3, NULL }; struct IntuiText itext1 = { 15, 0, JAM1, 26, 11, NULL, "CANCEL", NULL }; struct Gadget cangadg = { &prigadg, 174, 219, 100, 32, 0, RELVERIFY, BOOLGADGET, (APTR)&border3, NULL, &itext1, 0, NULL, GADGCAN, NULL }; struct IntuiText itext2 = { 15, 0, JAM1, 43, 11, NULL, "OK", NULL }; struct Gadget okgadg = { &cangadg, 24, 219, 100, 32, 0, RELVERIFY, BOOLGADGET, (APTR)&border3, NULL, &itext2, 0, NULL, GADGOK, NULL }; SHORT bordervec4[] = { 0, 0, 251, 0, 251, 14, 0, 14, 0, 1 }; struct Border border4 = { -2, -2, 15, 0, JAM1, 5, bordervec4, NULL }; UBYTE ifngadgbuff[80]; struct StringInfo ifngadginfo = { ifngadgbuff, (UBYTE *)undobuff, 0, 80, 0, 0, 0, 0, 0, 0, 0, 0, NULL }; struct Gadget ifngadg = { &okgadg, 25, 170, 250, 13, 0, 0, STRGADGET, (APTR)&border4, NULL, NULL, 0, (APTR)&ifngadginfo, 0, NULL }; UBYTE if4gadgbuff[80]; struct StringInfo if4gadginfo = { if4gadgbuff, (UBYTE *)undobuff, 0, 80, 0, 0, 0, 0, 0, 0, 0, 0, NULL }; struct Gadget if4gadg = { &ifngadg, 25, 114, 250, 13, 0, 0, STRGADGET, (APTR)&border4, NULL, NULL, 0, (APTR)&if4gadginfo, 0, NULL }; UBYTE if3gadgbuff[80]; struct StringInfo if3gadginfo = { if3gadgbuff, (UBYTE *)undobuff, 0, 80, 0, 0, 0, 0, 0, 0, 0, 0, NULL }; struct Gadget if3gadg = { &if4gadg, 25, 100, 250, 13, 0, 0, STRGADGET, (APTR)&border4, NULL, NULL, 0, (APTR)&if3gadginfo, 0, NULL }; UBYTE if2gadgbuff[80]; struct StringInfo if2gadginfo = { if2gadgbuff, (UBYTE *)undobuff, 0, 80, 0, 0, 0, 0, 0, 0, 0, 0, NULL }; struct Gadget if2gadg = { &if3gadg, 25, 86, 250, 13, 0, 0, STRGADGET, (APTR)&border4, NULL, NULL, 0, (APTR)&if2gadginfo, 0, NULL }; UBYTE if1gadgbuff[80]; struct StringInfo if1gadginfo = { if1gadgbuff, (UBYTE *)undobuff, 0, 80, 0, 0, 0, 0, 0, 0, 0, 0, NULL }; struct Gadget if1gadg = { &if2gadg, 25, 72, 250, 13, 0, 0, STRGADGET, (APTR)&border4, NULL, NULL, 0, (APTR)&if1gadginfo, 0, NULL }; UBYTE if0gadgbuff[80]; struct StringInfo if0gadginfo = { if0gadgbuff, (UBYTE *)undobuff, 0, 80, 0, 0, 0, 0, 0, 0, 0, 0, NULL }; struct Gadget if0gadg = { &if1gadg, 25, 58, 250, 13, 0, 0, STRGADGET, (APTR)&border4, NULL, NULL, 0, (APTR)&if0gadginfo, 0, NULL }; struct IntuiText itext23 = { 15, 0, JAM1, 300, 226, NULL, "Close WBench", NULL }; struct IntuiText itext22 = { 15, 0, JAM1, 448, 212, NULL, "Paths", &itext23 }; struct IntuiText itext21 = { 15, 0, JAM1, 448, 198, NULL, "VM", &itext22 }; struct IntuiText itext20 = { 15, 0, JAM1, 448, 184, NULL, "Htone", &itext21 }; struct IntuiText itext19 = { 15, 0, JAM1, 448, 170, NULL, "Fonts", &itext20 }; struct IntuiText itext18 = { 15, 0, JAM1, 448, 142, NULL, "Memory", &itext19 }; struct IntuiText itext17 = { 15, 0, JAM1, 300, 198, NULL, "Dpi.", &itext18 }; struct IntuiText itext16 = { 15, 0, JAM1, 300, 184, NULL, "Off.", &itext17 }; struct IntuiText itext15 = { 15, 0, JAM1, 300, 170, NULL, "X, Y", &itext16 }; struct IntuiText itext14 = { 15, 0, JAM1, 300, 142, NULL, "Page size", &itext15 }; struct IntuiText itext13 = { 15, 0, JAM1, 300, 114, NULL, "Printer density", &itext14 }; struct IntuiText itext12 = { 15, 0, JAM1, 416, 86, NULL, "4 Colour (CMYK)", &itext13 }; struct IntuiText itext11 = { 15, 0, JAM1, 416, 72, NULL, "3 Colour (RGB)", &itext12 }; struct IntuiText itext10 = { 15, 0, JAM1, 416, 58, NULL, "Black and white", &itext11 }; struct IntuiText itext9 = { 15, 0, JAM1, 300, 86, NULL, "IFF file", &itext10 }; struct IntuiText itext8 = { 15, 0, JAM1, 300, 72, NULL, "Screen", &itext9 }; struct IntuiText itext7 = { 15, 0, JAM1, 300, 58, NULL, "Printer", &itext8 }; struct IntuiText itext6 = { 15, 0, JAM1, 416, 30, NULL, "Colours", &itext7 }; struct IntuiText itext5 = { 15, 0, JAM1, 300, 30, NULL, "Output", &itext6 }; struct IntuiText itext4 = { 15, 0, JAM1, 25, 156, NULL, "IFF file name (pattern)", &itext5 }; struct IntuiText itext3 = { 15, 0, JAM1, 25, 30, NULL, "Startup file name(s)", &itext4 }; struct NewWindow newreqwindow = { 25, 60, 590, 260, 0, 15, GADGETUP|GADGETDOWN, ACTIVATE|SMART_REFRESH|NOCAREREFRESH, &if0gadg, NULL, POSTVER, NULL, NULL, 0, 0, 0, 0, CUSTOMSCREEN }; struct NewWindow newerrwindow = { 0, 100, 640, 100, 0, 15, 0, SIMPLE_REFRESH|NOCAREREFRESH|BACKDROP|BORDERLESS, NULL, NULL, NULL, NULL, NULL, 0, 0, 0, 0, CUSTOMSCREEN }; /* Stuff for the windows */ struct PropInfo hscrollinfo = /* Horizontal scroll proportional gadget */ { AUTOKNOB|FREEHORIZ, -1, -1, -1, -1 }; struct Image hscrollimage; struct Gadget hscrollgadg = { NULL, 0, -8, -14, 9, GRELBOTTOM|GRELWIDTH, BOTTOMBORDER|RELVERIFY, PROPGADGET, (APTR)&hscrollimage, NULL, NULL, 0, (APTR)&hscrollinfo, 0, NULL }; struct PropInfo vscrollinfo = /* Vertical scroll proportional gadget */ { AUTOKNOB|FREEVERT, -1, -1, -1, -1 }; struct Image vscrollimage; struct Gadget vscrollgadg = { &hscrollgadg, -15, 0, 16, -8, GRELRIGHT|GRELHEIGHT, RIGHTBORDER|RELVERIFY, PROPGADGET, (APTR)&vscrollimage, NULL, NULL, 0, (APTR)&vscrollinfo, 0, NULL }; struct NewWindow newbitwindow = /* Bitmap window. (Borders (4,2,18,10)) */ { 0, 49, 640, 463, -1, -1, 0, SIMPLE_REFRESH, &vscrollgadg, NULL, NULL, NULL, NULL, 0, 100, 0, 0, CUSTOMSCREEN }; struct NewWindow newintwindow = /* Interactive window */ { 0, 12, 640, 37, -1, -1, 0, SIZEBRIGHT|WINDOWSIZING|SMART_REFRESH|ACTIVATE, NULL, NULL, NULL, NULL, NULL, 0, 0, 0, 400, CUSTOMSCREEN }; struct IntuiText men2item2text = /* Menu strip */ { 7, 0, COMPLEMENT, 0, 0, NULL, "Interrupt", NULL }; struct MenuItem men2item2 = { NULL, 0, 40, 200, 11, ITEMTEXT|COMMSEQ|ITEMENABLED|HIGHCOMP, 0, (APTR)&men2item2text, NULL, 'I', NULL, MENUNULL }; struct IntuiText men2item1text = { 7, 0, COMPLEMENT, 0, 0, NULL, "Continue after pause", NULL }; struct MenuItem men2item1 = { &men2item2, 0, 20, 200, 11, ITEMTEXT|COMMSEQ|HIGHCOMP, 0, (APTR)&men2item1text, NULL, 'C', NULL, MENUNULL }; struct IntuiText men2item0text = { 7, 0, COMPLEMENT, 19, 0, NULL, "Pause every page", NULL }; struct MenuItem men2item0 = { &men2item1, 0, 0, 200,11, CHECKIT|ITEMTEXT|COMMSEQ|ITEMENABLED|HIGHCOMP|CHECKED, 0, (APTR)&men2item0text, NULL, 'P', NULL, MENUNULL }; struct Menu menu2 = { NULL, 160, 0, 80, 0, MENUENABLED, "Control", &men2item0 }; struct IntuiText men1item3text = { 7, 0, COMPLEMENT, 0, 0, NULL, "Interactive", NULL }; struct MenuItem men1item3 = { NULL, 0, 60, 128, 11, ITEMTEXT|COMMSEQ|ITEMENABLED|HIGHCOMP, 0, (APTR)&men1item3text, NULL, 'W', NULL, MENUNULL }; struct IntuiText men1item2text = { 7, 0, COMPLEMENT, 0, 0, NULL, "Run file", NULL }; struct MenuItem men1item2 = { &men1item3, 0, 40, 128, 11, ITEMTEXT|COMMSEQ|ITEMENABLED|HIGHCOMP, 0, (APTR)&men1item2text, NULL, 'R', NULL, MENUNULL }; struct IntuiText men1item1text = { 7, 0, COMPLEMENT, 0, 0, NULL, "Load file", NULL }; struct MenuItem men1item1 = { &men1item2, 0, 20, 128, 11, ITEMTEXT|COMMSEQ|ITEMENABLED|HIGHCOMP, 0, (APTR)&men1item1text, NULL, 'L', NULL, MENUNULL }; struct IntuiText men1item0text = { 7, 0, COMPLEMENT, 0, 0, NULL, "Load font", NULL }; struct MenuItem men1item0 = { &men1item1, 0, 0, 128, 11, ITEMTEXT|COMMSEQ|ITEMENABLED|HIGHCOMP, 0, (APTR)&men1item0text, NULL, 'F', NULL, MENUNULL }; struct Menu menu1 = { &menu2, 80, 0, 80, 0, 0, "File", &men1item0 }; struct IntuiText men0item1text = { 7, 0, COMPLEMENT, 0, 0, NULL, "Quit", NULL }; struct MenuItem men0item1 = { NULL, 0, 20, 100, 11, ITEMTEXT|ITEMENABLED|HIGHCOMP, 0, (APTR)&men0item1text, NULL, NULL, NULL, MENUNULL }; struct IntuiText men0item0text = { 7, 0, COMPLEMENT, 0, 0, NULL, "Restart", NULL }; struct MenuItem men0item0 = { &men0item1, 0, 0, 100, 11, ITEMTEXT|ITEMENABLED|HIGHCOMP, 0, (APTR)&men0item0text, NULL, NULL, NULL, MENUNULL }; struct Menu menu0 = { &menu1, 0, 0, 80, 0, 0, "Project", &men0item0 }; /* Arguments */ int arglen, argwb, argfilec, argsizec, argmemc; int argprint, argscreen, argiff, argint, argclosewb; char *argbuf, *argsizev[5], *argmemv[5]; char *argfilev[] = { (char *) &if0gadgbuff[0], (char *) &if1gadgbuff[0], (char *) &if2gadgbuff[0], (char *) &if3gadgbuff[0], (char *) &if4gadgbuff[0] }; char *argifn = (char *) &ifngadgbuff[0]; char *argcon = "CON"; char *argkey[] = { "IFF", "SCREEN", "PRINTER", "INTERACTIVE", "SIZE", "MEM", "CLOSEWB", "CONDEV", NULL }; /* Lattice stuff for using Arp FPrintf/SPrintf */ LONG ArpFPrintf(BPTR, char*,); LONG ArpSPrintf(char *, char*,); # pragma libcall ArpBase ArpFPrintf 00EA 98003 # pragma libcall ArpBase ArpSPrintf 0282 98003 LONG __stdargs FPrintf(BPTR fh, char *format,) { return ArpFPrintf(fh, format, (&format)+1); } LONG __stdargs SPrintf(char *string, char *format,) { return ArpSPrintf(string, format, (&format)+1); } /* Startup code */ extern void main(int argc, char **argv); void _main(char *line) { struct DiskObject *diskobj; char *diskname; char *argv[32]; int argc; /* If this is a workbench startup construct the arguments string. We * find the name of our icon from the first argument. Then we laod the * icon and look for an ARGS string in the tooltypes. We concatenate * the program name and the arguments into an Alloc'ed buffer */ if (WBenchMsg && WBenchMsg->sm_NumArgs) { diskname = WBenchMsg->sm_ArgList[0].wa_Name; line = NULL; IconBase = (struct IconBase *) OpenLibrary("icon.library", 0); if (IconBase) { diskobj = GetDiskObject(diskname); line = FindToolType(diskobj->do_ToolTypes, "ARGS"); } if (line) { arglen = strlen(diskname) + strlen(line) + 2; argbuf = AllocMem(arglen, MEMF_CLEAR); } if (argbuf) { strcpy(argbuf, diskname); strcat(argbuf, " "); strcat(argbuf, line); } line = argbuf; if (diskobj) FreeDiskObject(diskobj); if (IconBase) CloseLibrary((struct Library *) IconBase); } /* Parse the arguments to break words and strip quotes. N.B. the * main program can determine that the arument was quoted by inspecting * the preceeding character */ argc = 0; if (line == NULL) goto endline; for (;;) { while (*line == ' ' || *line == '\t' || *line == '\n') line++; if (*line == 0) break; if (argc == 32) { argc = 0; goto endline; } if (*line == '"') { argv[argc] = ++line; while (*line != '"') { if (*line == 0) { argc = 0; goto endline; } line++; } } else { argv[argc] = line; while (*line != ' ' && *line != '\t' && *line != '\n') { if (*line == 0) { argc++; goto endline; } line++; } } *line++ = 0; argc++; } endline: /* Set up the standard input/output files */ if (WBenchMsg) /* Workbench startup, no files */ { argwb = 1; } else /* CLI startup, open stderr */ { errfh = Open("*", MODE_OLDFILE); if (errfh == NULL) { retcode = 20; goto tidyexit; } } /* Call the main program */ main(argc, argv); /* Tidy up and exit */ tidyexit: if (argbuf) FreeMem(argbuf, arglen); if (errfh) Close(errfh); XCEXIT(retcode); } /* Main program */ void main(int argc, char **argv) { struct Message *msg; struct Gadget *gadget; char *s; int *ip, i, ch, l; int xsize, ysize, ssize, xoff, yoff, xden, yden, pden; process = (struct Process *) FindTask(NULL); syswindow = (struct Window *) process->pr_WindowPtr; /* Open the libraries */ GfxBase = (struct GfxBase *) OpenLibrary("graphics.library", 0); IntuitionBase = (struct IntuitionBase *) OpenLibrary("intuition.library", 0); ArpBase = (struct ArpBase *) OpenLibrary("arp.library", 39); if (GfxBase == NULL || IntuitionBase == NULL || ArpBase == NULL) { errmsg("can't open libraries (you need arp.library V39+)"); goto errorexit; } # ifndef STATICLINK PSbase = OpenLibrary("post.library", POSTVERNO); if (PSbase == NULL) { errmsg("can't open post.library"); goto errorexit; } # endif /* Parse the arguments and keywords. See the usage string below */ if (argc == 0) goto badargs; argc--; argv++; if (argc == 0 || argwb) argint = 1; if (argc == 1 && strcmp(*argv, "?") == 0) goto usage; while (argc--) { s = *argv++; i = -1; if (s[-1] != '"') for (;;) { i++; if (argkey[i] == NULL) { i = -1; break; } if (stricmp(s, argkey[i]) == 0) break; } switch (i) { case 0: /* IFF */ if (argc == 0 || strlen(*argv) >= 80) goto badargs; argc--; argiff = 1; strcpy(argifn, *argv++); break; case 1: /* SCREEN */ argscreen = 1; break; case 2: /* PRINTER */ argprint = 1; break; case 3: /* INTERACTIVE */ argint = 1; break; case 4: /* SIZE */ if (argc == 0) goto badargs; argc--; if (argsizec == 5) goto badargs; argsizev[argsizec++] = *argv++; break; case 5: /* MEM */ if (argc == 0) goto badargs; argc--; if (argmemc == 5) goto badargs; argmemv[argmemc++] = *argv++; break; case 6: /* CLOSEWB */ argclosewb = 1; break; case 7: /* CONDEV */ if (argc == 0) goto badargs; argc--; argcon = *argv++; break; default: if (argfilec == 5 || strlen(s) >= 80) goto badargs; strcpy(argfilev[argfilec++], s); } } if (!argscreen && !argiff && !argint) argprint = 1; if (argscreen) argint = 1; /* Set up the screen size, adjusting for interlace */ newscreen.Width = GfxBase->NormalDisplayColumns; newscreen.Height = GfxBase->NormalDisplayRows * 2; if (newscreen.Width < 400) newscreen.Width = 400; if (newscreen.Height < 300) newscreen.Height = 300; /* Set up the default page size. For printer output we get the defaults * from preferences; otherwise we default to an A4 inch page at 75 dpi. * with 3 colour planes, trimming the width to fit onto the screen. (We * can't quite fit A4 onto a standard 640 pixel wide screen - 8.24 inches * instead of 8.26). */ bitmap.BytesPerRow = 1; bitmap.Rows = 1; bitmap.Flags = 0; bitmap.Depth = parm.page.depth = 3; if (argprint) { setprinter(); if (prport == NULL) { errmsg("can't open printer device"); goto errorexit; } } else { parm.page.xsize = 824 * 75 / 100; parm.page.ysize = 1169 * 75 / 100; parm.page.xoff = parm.page.yoff = 0; parm.page.xden = parm.page.yden = 75; if (parm.page.xsize > newscreen.Width - 22) parm.page.xsize = newscreen.Width - 22; } parm.page.ydir = -1; /* Parse the "SIZE xyod..s..p.bc." options */ xsize = ysize = ssize = xden = yden = pden = 0; for (i = 0; i < argsizec; i++) { s = argsizev[i]; for (;;) { ch = *s++; if (ch == 0) break; ch = tolower(ch); switch (ch) { case 'x': if (tolower(*s) == 'o') { s++; if (!strtoint(&s, &xoff)) goto badvalue; parm.page.xoff = xoff; continue; } else if (tolower(*s) == 'd') { s++; ip = &xden; } else ip = &xsize; break; case 'y': if (tolower(*s) == 'o') { s++; if (!strtoint(&s, &yoff)) goto badvalue; parm.page.yoff = yoff; continue; } else if (tolower(*s) == 'd') { s++; ip = &yden; } else ip = &ysize; break; case 's': ip = &ssize; break; case 'p': ip = &pden; break; case 'd': { if (!strtoint(&s, &xden)) goto badvalue; yden = xden; continue; } case 'b': parm.page.depth = 1; continue; case 'c': ch = *s; if (ch == '3') { s++; parm.page.depth = 3; } else if (ch == '4') { s++; parm.page.depth = 4; } else parm.page.depth = 3; continue; default: goto badvalue; } if (!strtoint(&s, ip)) goto badvalue; } } if (xden != 0) parm.page.xden = xden; if (yden != 0) parm.page.yden = yden; if (xsize != 0) parm.page.xsize = xsize; if (ysize != 0) parm.page.ysize = ysize; if (pden != 0) { prden = pden; if (argprint) setprintden(); } /* Set up the default memory sizes */ parm.memvlen = defmemvlen; parm.memflen = defmemflen; parm.memllen = defmemllen; parm.memhlen = defmemhlen; /* Parse the "MEM fhlv.." options */ for (i = 0; i < argmemc; i++) { s = argmemv[i]; for (;;) { ch = *s++; if (ch == 0) break; ch = tolower(ch); switch (ch) { case 'f': ip = &parm.memflen; break; case 'h': ip = &parm.memhlen; break; case 'l': ip = &parm.memllen; break; case 'v': ip = &parm.memvlen; break; default: goto badvalue; } if (!strtoint(&s, ip)) goto badvalue; } } /* We only need the file requestors if we are interactive */ if (argint) { filereq1 = ArpAllocFreq(); filereq2 = ArpAllocFreq(); if (filereq1 == NULL || filereq2 == NULL) { errmsg("can't get file requestors"); goto errorexit; } } /* We seem to have to explicitly load the font from the disk before * Intuition can be depended upon to use it */ if (argint) { DiskfontBase = OpenLibrary("diskfont.library", 0); if (DiskfontBase) { textfont = OpenDiskFont(&topaz11); CloseLibrary(DiskfontBase); } if (textfont == NULL) { errmsg("can't find font topaz/11"); goto errorexit; } } /* Set up the color map according to the number of bitplanes */ setcmap: restarterror = 0; if (!argint) newscreen.Depth = parm.page.depth; colormap.Count = 1 << newscreen.Depth; if (newscreen.Depth == 1) colormap.ColorTable = (APTR) bcolors; else colormap.ColorTable = (APTR) ccolors; /* Open the screen and load the color map */ if (argint) { screen = OpenScreen(&newscreen); if (screen == NULL) { errmsg("can't open screen"); goto errorexit; } newerrwindow.Screen = screen; newreqwindow.Screen = screen; newbitwindow.Screen = screen; newintwindow.Screen = screen; LoadRGB4(&screen->ViewPort, (short *) colormap.ColorTable, colormap.Count); newerrwindow.Width = newscreen.Width; errwindow = OpenWindow(&newerrwindow); if (errwindow == NULL) { errmsg("can't open error window"); goto errorexit; } process->pr_WindowPtr = (APTR) errwindow; } restarterror = 1; restart: if (fatalerror) goto tidyexit; retcode = 0; tidyup(); if (argint) { if (argclosewb) CloseWorkBench(); if (requested == 0) { /* Put up the parameters requestor (window) */ setreqgadgets(); newreqwindow.IDCMPFlags = GADGETUP|GADGETDOWN; reqwindow = OpenWindow(&newreqwindow); if (reqwindow == NULL) { errmsg("can't open parameters window"); goto restart; } PrintIText(reqwindow->RPort, &itext3, 0, 0); /* Loop handling gadget messages */ for (;;) { WaitPort(reqwindow->UserPort); while (msg = GetMsg(reqwindow->UserPort)) { gadget = (struct Gadget *) ((struct IntuiMessage *) msg)->IAddress; i = gadget->GadgetID; switch (i) { case GADGOK: case GADGCAN: goto closereq; case GADGPRI: argprint = getgadgbool(gadget); if (argprint) { setprinter(); if (prport == NULL) { argprint = 0; errmsg("can't open printer device"); i = GADGRST; goto closereq; } } goto setgadg; case GADGPD1: case GADGPD2: case GADGPD3: case GADGPD4: case GADGPD5: case GADGPD6: case GADGPD7: if (argprint) { prden = i - (GADGPD1 - 1); setprintden(); goto setgadg; } break; case GADGBW: parm.page.depth = 1; goto setgadg; case GADGC3: parm.page.depth = 3; goto setgadg; case GADGC4: parm.page.depth = 4; setgadg: setreqgadgets(); break; case GADGABS: getgadgabs(gadget); } ReplyMsg(msg); } } /* Close the requester window */ closereq: ModifyIDCMP(reqwindow, CLOSEWINDOW); while (msg) { ReplyMsg(msg); msg = GetMsg(reqwindow->UserPort); } CloseWindow(reqwindow); reqwindow = NULL; if (i == GADGCAN) goto tidyexit; if (i == GADGRST) goto restart; getreqgadgets(); /* If we have changed our mind about the number of bitplanes * close the screen and go back to reopen it with the new depth */ if (parm.page.depth != newscreen.Depth) { process->pr_WindowPtr = (APTR) syswindow; CloseWindow(errwindow); errwindow = NULL; CloseScreen(screen); screen = NULL; newscreen.Depth = parm.page.depth; requested = 1; goto setcmap; } } requested = 0; } /* Set the size of the interactive windows */ if (argint) { newbitwindow.Width = newscreen.Width; newbitwindow.Height = newscreen.Height - newintwindow.TopEdge - newintwindow.Height; newbitwindow.TopEdge = newscreen.Height - newbitwindow.Height; newintwindow.Width = newscreen.Width; newintwindow.MaxHeight = newscreen.Height - newintwindow.TopEdge - newbitwindow.MinHeight; /* Locate the visible part of the bitmap within its window, adjusting * for the borders */ winxbase = 4; winybase = 2; winxsize = newbitwindow.Width - 22; winysize = newbitwindow.Height - 12; /* Set the page size. It must not be smaller than the interior of the * interactive window. We may not need the horizontal scroll bar. Each * bitmap row must start on a word boundary */ if (parm.page.xsize <= winxsize) { winysize += 8; vscrollgadg.NextGadget = 0; vscrollgadg.Height = 0; } else { vscrollgadg.NextGadget = &hscrollgadg; vscrollgadg.Height = -8; } if (parm.page.xsize < winxsize) parm.page.xsize = winxsize; if (parm.page.ysize < winysize) parm.page.ysize = winysize; } parm.page.ybase = 0; parm.page.yheight = parm.page.ysize; if (!argint) if (ssize != 0 && ssize < parm.page.ysize) parm.page.ysize = ssize; if (parm.page.xsize == 0 || parm.page.ysize == 0) { errmsg("page size not set in preferences"); goto restart; } parm.page.xbytes = (parm.page.xsize + 15) >> 3 & 0xfffffffe; parm.page.len = parm.page.xbytes * parm.page.ysize; /* Allocate the page buffer. It must be in chip memory if we are * outputting to a screen */ for (i = 0; i < parm.page.depth; i++) { if ((parm.page.buf[i] = AllocMem(parm.page.len, (argscreen ? MEMF_CHIP|MEMF_CLEAR : MEMF_PUBLIC|MEMF_CLEAR))) == NULL) { errmsg("can't get page buffer"); goto restart; } } /* Initialise the bitmap */ bitmap.BytesPerRow = parm.page.xbytes; bitmap.Rows = parm.page.ysize; bitmap.Flags = 0; bitmap.Depth = parm.page.depth; memcpy((char *) bitmap.Planes, (char *) parm.page.buf, sizeof bitmap.Planes); /* For interactive working, set up the windows */ if (argint) { /* Finish initialising the gadgets and open the windows */ hscrollinfo.HorizPot = 0; vscrollinfo.VertPot = 0xffff; hscrollinfo.HorizBody = (0xffff * winxsize) / parm.page.xsize; vscrollinfo.VertBody = (0xffff * winysize) / parm.page.ysize; winxpos = 0; winypos = parm.page.ysize - winysize; bitwindow = OpenWindow(&newbitwindow); intwindow = OpenWindow(&newintwindow); if (bitwindow == NULL || intwindow == NULL) { errmsg("can't open windows"); goto restart; } /* Set up new console streams. Black on white characters */ SPrintf((char *) undobuff, "%s:W%lx", argcon, intwindow); confh = Open((char *) undobuff, MODE_OLDFILE); if (confh == NULL) { errmsg("can't open console device (you need ConMan V1.3+)"); goto restart; } FPrintf(confh, "\x9b\x33\x37\x6d"); } /* Create the menu handler task */ if (argint) { mainport = CreatePort(NULL, 0); if (mainport) { menumsg.ExecMessage.mn_ReplyPort = mainport; menumsg.action = PSACTOPEN; menumsg.bitmap = &bitmap; menutask = CreateTask("post.menu", 6, (APTR) menuproc, 2000); } if (menutask) sendmenu(PSACTOPEN); if (menutask == NULL) { errmsg("can't create menu handler"); goto restart; } } /* Initialise for interpretation */ insertbreak(); SetExcept(~0, SIGBREAKF_CTRL_C); breakset = 1; insertftrap(); ftrapset = 1; # ifndef STATICLINK parm.flushfunc = (APTR) flushpage; parm.copyfunc = (APTR) copypage; # endif if (argint) { parm.infh = confh; parm.outfh = confh; parm.errfh = confh; } else { parm.infh = Input(); parm.outfh = Output(); parm.errfh = errfh; } arec = PScreateact(&parm); if (arec == 0) { errmsg("can't get memory"); retcode = 20; goto restart; } if ((unsigned) arec <= errmax) retcode = 10; /* Interpret the argument files */ for (i = 0; i < 5; i++) { s = argfilev[i]; if (s[0] != 0) { if (retcode != 0) break; errcode = PSintstring(arec, s, -1, PSFLAGFILE|PSFLAGCLEAR|PSFLAGERASE); if (errcode) retcode = 10; } } /* Execute menu commands */ if (argint) { for (;;) { sendmenu(retcode == 0 ? PSACTCOMMAND : PSACTEXIT); s = menumsg.string; switch (menumsg.command) { case PSCOMQUIT: goto quit; case PSCOMRESTART: PSdeleteact(arec); arec = 0; goto restart; case PSCOMFILEF: i = PSFLAGFILE|PSFLAGCLEAR|PSFLAGERASE; strcpy(filereq1->fr_Dir, "PSFonts:"); filereq = filereq1; filereq->fr_Hail = hailfilef; goto freq; case PSCOMFILEL: i = PSFLAGFILE|PSFLAGCLEAR|PSFLAGERASE; filereq = filereq2; filereq->fr_Hail = hailfilen; goto freq; case PSCOMFILER: i = PSFLAGFILE|PSFLAGCLEAR|PSFLAGERASE|PSFLAGSAVE; filereq = filereq2; filereq->fr_Hail = hailfiles; freq: filereq->fr_Window = intwindow; filereq->fr_FuncFlags |= (FRF_NewIDCMP|FRF_DoColor); filereq->fr_LeftEdge = 170; filereq->fr_TopEdge = 150; if (FileRequest(filereq) == NULL) break; l = strlen(filereq->fr_Dir); TackOn(filereq->fr_Dir, filereq->fr_File); PSintstring(arec, filereq->fr_Dir, -1, i); filereq->fr_Dir[l] = 0; break; case PSCOMINTER: PSintstring(arec, "%stdin", -1, PSFLAGFILE|PSFLAGCLEAR|PSFLAGERASE|PSFLAGSAVE| PSFLAGINTER); break; } } } quit: PSdeleteact(arec); arec = 0; goto tidyexit; /* Argument errors and usage query */ badargs: errmsg("arguments bad, or value missing or too long"); goto badusage; badvalue: errmsg("argument bad value"); badusage: retcode = 20; usage: if (!argwb) FPrintf(errfh, "post: usage:\n" " post [files...] [IFF file] [SCREEN] [PRINTER] [INTERACTIVE]\n" " [SIZE xyod..s..p.bc.] [MEM fhlv..] [CLOSEWB] [CONDEV con]\n"); goto tidyexit; /* Tidy up and exit */ errorexit: retcode = 20; tidyexit: tidyup(); process->pr_WindowPtr = (APTR) syswindow; if (errwindow) CloseWindow(errwindow); if (screen) CloseScreen(screen); if (textfont) CloseFont(textfont); if (propen) CloseDevice((struct IORequest *) &prreq); if (prport) DeletePort(prport); # ifndef STATICLINK if (PSbase) CloseLibrary(PSbase); # endif if (ArpBase) CloseLibrary((struct Library *) ArpBase); if (GfxBase) CloseLibrary((struct Library *) GfxBase); if (IntuitionBase) { OpenWorkBench(); CloseLibrary((struct Library *) IntuitionBase); } } /* Display an error requestor or message */ struct IntuiText bodytext2 = { AUTOFRONTPEN, AUTOBACKPEN, AUTODRAWMODE, AUTOLEFTEDGE + 32, AUTOTOPEDGE + 11, AUTOITEXTFONT, NULL, NULL }; struct IntuiText bodytext = { AUTOFRONTPEN, AUTOBACKPEN, AUTODRAWMODE, AUTOLEFTEDGE, AUTOTOPEDGE, AUTOITEXTFONT, POSTVER " Error", &bodytext2 }; struct IntuiText postext = { AUTOFRONTPEN, AUTOBACKPEN, AUTODRAWMODE, AUTOLEFTEDGE, AUTOTOPEDGE, AUTOITEXTFONT, "RETRY", NULL }; struct IntuiText negtext = { AUTOFRONTPEN, AUTOBACKPEN, AUTODRAWMODE, AUTOLEFTEDGE, AUTOTOPEDGE, AUTOITEXTFONT, "CANCEL", NULL }; void errmsg(char *string) { int width; if (IntuitionBase && (errwindow || argwb || ArpBase == NULL)) { bodytext2.IText = string; width = IntuiTextLength(&bodytext2) + 70; if (width < 200) width = 200; if (!AutoRequest(errwindow, &bodytext, (restarterror ? &postext : NULL), &negtext, 0, 0, width, 70)) fatalerror = 1; return; } if (ArpBase && !argwb) { FPrintf(errfh, "post: %s\n", string); fatalerror = 1; return; } fatalerror = 1; } /* Tidy up */ void tidyup(void) { int i; if (breakset) { SetExcept(0, SIGBREAKF_CTRL_C); deletebreak(); breakset = 0; } if (ftrapset) { deleteftrap(); ftrapset = 0; } if (menuport) sendmenu(PSACTCLOSE); if (mainport) { DeletePort(mainport); mainport = NULL; } if (confh) { Close(confh); confh = NULL; } /* N.B. some versions of ConMan close the window themselves, so we * don't close the interactive window it it appears to have been * closed already */ if (bitwindow) { CloseWindow(bitwindow); bitwindow = NULL; } if (intwindow) { if (screen->FirstWindow == intwindow || errwindow->NextWindow == intwindow) CloseWindow(intwindow); intwindow = NULL; } for (i = 0; i < parm.page.depth; i++) if (parm.page.buf[i]) { FreeMem(parm.page.buf[i], parm.page.len); parm.page.buf[i] = NULL; } } /* Open the printer device and set up the page size */ void setprinter(void) { if (propen == 0) { if (OpenDevice("printer.device", 0, (struct IOReqest *) &prreq, 0) != 0) return; propen = 1; } if (prport == NULL) { prport = CreatePort(NULL, 0); if (prport == NULL) return; prreq.io_Message.mn_ReplyPort = prport; prsig = 1 << prport->mp_SigBit; prdata = (struct PrinterData *) prreq.io_Device; prextdata = &prdata->pd_SegmentData->ps_PED; prprefs = &prdata->pd_Preferences; prden = prprefs->PrintDensity; } if ((prprefs->PrintShade & SHADE_COLOR) == 0) parm.page.depth = 1; setprintden(); } /* Set the printer density */ void setprintden(void) { int pxsize, pysize, xy; /* New density, call the device driver to change its extended data. No * error check */ if (prden > 7) prden = 7; if (prden != prprefs->PrintDensity) { prreq.io_Command = PRD_DUMPRPORT; prrast.BitMap = &bitmap; prreq.io_RastPort = &prrast; prreq.io_ColorMap = (struct ColorMap *) &colormap; prreq.io_Modes = 0; prreq.io_SrcX = 0; prreq.io_SrcY = 0; prreq.io_SrcWidth = 1; prreq.io_SrcHeight = 1; prreq.io_DestCols = 1; prreq.io_DestRows = 1; prreq.io_Special = (SPECIAL_DENSITY1 * prden) | SPECIAL_NOPRINT; prprefs->PrintDensity = prden; DoIO((struct IORequest *) &prreq); } /* Extract the page size and density from the printer device preferences * and extended data */ parm.page.xden = prextdata->ped_XDotsInch; parm.page.yden = prextdata->ped_YDotsInch; if (prprefs->PrintFlags & PIXEL_DIMENSIONS) { pxsize = prprefs->PrintMaxWidth; pysize = prprefs->PrintMaxHeight; } else if (prprefs->PrintFlags & (BOUNDED_DIMENSIONS|ABSOLUTE_DIMENSIONS)) { pxsize = prprefs->PrintMaxWidth * parm.page.xden / 10; pysize = prprefs->PrintMaxHeight * parm.page.yden / 10; } if (prprefs->PrintAspect & ASPECT_VERT) { xy = pxsize; pxsize = pysize; pysize = xy; } if (pxsize != 0) parm.page.xsize = pxsize; if (pysize != 0) parm.page.ysize = pysize; parm.page.xoff = 0; parm.page.yoff = 0; } /* Set all requester gadgets */ void setreqgadgets(void) { setgadgbool(&bwgadg, (parm.page.depth == 1)); setgadgbool(&c3gadg, (parm.page.depth == 3)); setgadgbool(&c4gadg, (parm.page.depth == 4)); setgadgbool(&pd1gadg, (prden == 1)); setgadgbool(&pd2gadg, (prden == 2)); setgadgbool(&pd3gadg, (prden == 3)); setgadgbool(&pd4gadg, (prden == 4)); setgadgbool(&pd5gadg, (prden == 5)); setgadgbool(&pd6gadg, (prden == 6)); setgadgbool(&pd7gadg, (prden == 7)); setgadgint(&xgadg, parm.page.xsize); setgadgint(&ygadg, parm.page.ysize); setgadgint(&xogadg, parm.page.xoff); setgadgint(&yogadg, parm.page.yoff); setgadgint(&xdgadg, parm.page.xden); setgadgint(&ydgadg, parm.page.yden); if (reqwindow == NULL) { setgadgbool(&prigadg, argprint); setgadgbool(&scrgadg, argscreen); setgadgbool(&iffgadg, argiff); setgadgbool(&cwbgadg, argclosewb); setgadgint(&mfgadg, parm.memflen); setgadgint(&mhgadg, parm.memhlen); setgadgint(&mvgadg, parm.memvlen); setgadgint(&mlgadg, parm.memllen); } enablegadg(&pd1gadg, argprint); enablegadg(&pd2gadg, argprint); enablegadg(&pd3gadg, argprint); enablegadg(&pd4gadg, argprint); enablegadg(&pd5gadg, argprint); enablegadg(&pd6gadg, argprint); enablegadg(&pd7gadg, argprint); } /* Get all requester gadgets */ void getreqgadgets(void) { argscreen = getgadgbool(&scrgadg); argiff = getgadgbool(&iffgadg); if (argifn[0] == 0) argiff = 0; parm.page.depth = getgadgbool(&bwgadg) ? 1 : getgadgbool(&c3gadg) ? 3 : 4; argclosewb = getgadgbool(&cwbgadg); parm.page.xsize = getgadgabs(&xgadg); parm.page.ysize = getgadgabs(&ygadg); parm.page.xoff = getgadgint(&xogadg); parm.page.yoff = getgadgint(&yogadg); parm.page.xden = getgadgabs(&xdgadg); parm.page.yden = getgadgabs(&ydgadg); parm.memflen = getgadgabs(&mfgadg); parm.memhlen = getgadgabs(&mhgadg); parm.memvlen = getgadgabs(&mvgadg); parm.memllen = getgadgabs(&mlgadg); } /* Enable a gadget */ void enablegadg(struct Gadget *gadget, int enable) { if ((gadget->Flags & GADGDISABLED) != (enable ? 0 : GADGDISABLED)) { if (reqwindow) RemoveGadget(reqwindow, gadget); if (enable) gadget->Flags &= ~GADGDISABLED; else gadget->Flags |= GADGDISABLED; if (reqwindow) { AddGadget(reqwindow, gadget, 65535); RefreshGadgets(gadget, reqwindow, NULL); } } } /* Set the value of a boolean requester gadget */ void setgadgbool(struct Gadget *gadget, int value) { if (value == getgadgbool(gadget)) return; if (reqwindow) RemoveGadget(reqwindow, gadget); if (value) gadget->Flags |= SELECTED; else gadget->Flags &= ~SELECTED; if (reqwindow) { AddGadget(reqwindow, gadget, 65535); RefreshGadgets(gadget, reqwindow, NULL); } } /* Get the value of a boolean gadget */ int getgadgbool(struct Gadget *gadget) { return (gadget->Flags & SELECTED) != 0; } /* Set the value of an integer requester gadget */ void setgadgint(struct Gadget *gadget, int value) { struct StringInfo *info; if (reqwindow) { if (value == getgadgint(gadget)) return; RemoveGadget(reqwindow, gadget); } info = (struct StringInfo *) gadget->SpecialInfo; info->LongInt = value; SPrintf((char *) info->Buffer, "%ld", value); if (reqwindow) { AddGadget(reqwindow, gadget, 65535); RefreshGadgets(gadget, reqwindow, NULL); } } /* Get the value of an integer gadget */ int getgadgint(struct Gadget *gadget) { struct StringInfo *info = (struct StringInfo *) gadget->SpecialInfo; return (int) info->LongInt; } /* Get the absolute value of an integer gadget */ int getgadgabs(struct Gadget *gadget) { int value = getgadgint(gadget); if (value < 0) { value = 0; setgadgint(gadget, value); } return value; } /* String to integer conversion; digits only, with error check */ int strtoint(char **sp, int *ip) { char *s = *sp; int i = 0; int ch; for (;;) { ch = *s; if (ch < '0' || ch > '9') break; i = i * 10 + (ch - '0'); s++; } if (s == *sp) return 0; else { *sp = s; *ip = i; return 1; } } /* Send a mesage to the menu handler task */ void sendmenu(int action) { if (action != PSACTOPEN) { menumsg.action = action; menumsg.result = retcode; menumsg.errnum = errcode; PutMsg(menuport, (struct Message *) &menumsg); } WaitPort(mainport); GetMsg(mainport); retcode = menumsg.result; } /* The menu handler task */ static int pause = 1; void __saveds menuproc(void) { struct Message *msg; char *title, *oldtitle, *savetitle; int height, i, j; title = titlestart; height = newintwindow.Height; msg = (struct Message *) &menumsg; /* Loop handling messages. We access the initial message directly, * rather than getting it from the menu port, as we havn't created the * port yet */ for (;;) { /* Message from main program */ if ((struct PSmessage *) msg == &menumsg) { switch (menumsg.action) { /* Open the windows and initialise */ case PSACTOPEN: menuport = CreatePort(NULL, 0); if (menuport == NULL) { menumsg.result = 20; goto end; } bitwindow->UserPort = menuport; intwindow->UserPort = menuport; ModifyIDCMP(bitwindow, REFRESHWINDOW|ACTIVEWINDOW|GADGETUP); ModifyIDCMP(intwindow, REFRESHWINDOW|MENUPICK); menu2.Flags |= MENUENABLED; SetMenuStrip(intwindow, &menu0); SetWindowTitles(intwindow, NULL, (UBYTE *) title); ReplyMsg(msg); break; /* Close the windows and tidy up */ case PSACTCLOSE: ClearMenuStrip(intwindow); ModifyIDCMP(bitwindow, CLOSEWINDOW); ModifyIDCMP(intwindow, CLOSEWINDOW); bitwindow->UserPort = NULL; intwindow->UserPort = NULL; for (;;) { msg = GetMsg(menuport); if (msg == NULL) break; ReplyMsg(msg); } DeletePort(menuport); menuport = NULL; goto end; /* Flush the bitmap to its window */ case PSACTFLUSH: i = menumsg.y1; j = menumsg.y2; if (i < winypos) i = winypos; if (j < winypos) j = winypos; if (i > winypos + winysize) i = winypos + winysize; if (j > winypos + winysize) j = winypos + winysize; if (j > i && argscreen) { BltBitMapRastPort(&bitmap, winxpos, i, bitwindow->RPort, winxbase, winybase + i - winypos, winxsize, j - i, 0xC0); } ReplyMsg(msg); break; /* Pause at the end of a page */ case PSACTPAUSE: if (pause) { savetitle = title; title = titlepaused; SetWindowTitles(intwindow, NULL, (UBYTE *) title); OnMenu(intwindow, 2 | SHIFTITEM(1)); } else ReplyMsg(msg); break; /* Get the next command */ case PSACTCOMMAND: title = titlewait; SetWindowTitles(intwindow, NULL, (UBYTE *) title); OnMenu(intwindow, 0 | SHIFTITEM(NOITEM)); OnMenu(intwindow, 1 | SHIFTITEM(NOITEM)); break; /* Get a quit or restart command */ case PSACTEXIT: title = titlewait; SetWindowTitles(intwindow, NULL, (UBYTE *) title); OnMenu(intwindow, 0 | SHIFTITEM(NOITEM)); OffMenu(intwindow, 2 | SHIFTITEM(NOITEM)); break; } } /* Message from Intuition */ else { switch (((struct IntuiMessage *) msg)->Class) { /* Make the interactive window the active one, but only if * the scroll gadget knobs in the bitmapped window are not * currently hit (so as not to prevent dragging them). (If * someone is dragging them we will get a GADGETUP message * when he lets go.) */ case ACTIVEWINDOW: if (!(hscrollgadg.Flags & SELECTED) && !(vscrollgadg.Flags & SELECTED)) ActivateWindow(intwindow); break; /* Refresh a window */ case REFRESHWINDOW: /* Refresh the bitmapped window */ if (((struct IntuiMessage *)msg)->IDCMPWindow == bitwindow) { BeginRefresh(bitwindow); if (argscreen) BltBitMapRastPort(&bitmap, winxpos, winypos, bitwindow->RPort, winxbase, winybase, winxsize, winysize, 0xC0); EndRefresh(bitwindow, TRUE); } /* We don't actually refresh the interactive window, but * instead we use this event to tell us when it has * changed size, so we can adjust the size and position * of the bitmapped window to match. (Despite what the * manual says we seem to get the refresh message even * when the window gets smaller */ else { i = intwindow->Height; j = i - height; height = i; if (j < 0) { MoveWindow(bitwindow, 0, j); SizeWindow(bitwindow, 0, -j); } else if (j > 0) { SizeWindow(bitwindow, 0, -j); MoveWindow(bitwindow, 0, j); } winypos += j; if (winypos < 0) winypos = 0; winysize -= j; ModifyProp(&vscrollgadg, bitwindow, NULL, AUTOKNOB|FREEVERT, -1, (0xffff * winypos) / (parm.page.ysize - winysize), -1, (0xffff * winysize) / parm.page.ysize); } break; /* Scroll the bitmapped window. Make sure we can scroll to * the edges of the page, even after rounding erors */ case GADGETUP: ActivateWindow(intwindow); if (((struct IntuiMessage *) msg)->IAddress == (APTR) &hscrollgadg) { i = (parm.page.xsize - winxsize); j = (i * hscrollinfo.HorizPot) / 65535; if (j < i / 30) j = 0; if (i - j < i / 30) j = i; winxpos = j; } else if (((struct IntuiMessage *) msg)->IAddress == (APTR) &vscrollgadg) { i = (parm.page.ysize - winysize); j = (i * vscrollinfo.VertPot) / 65535; if (j < i / 30) j = 0; if (i - j < i / 30) j = i; winypos = j; } if (argscreen) BltBitMapRastPort(&bitmap, winxpos, winypos, bitwindow->RPort, winxbase, winybase, winxsize, winysize, 0xC0); break; /* Menu selection. We don't implement extended selection * to avoid real time problems, and it wouldn't be useful * for our range of choices anyway */ case MENUPICK: i = ((struct IntuiMessage *) msg)->Code; j = ITEMNUM(i); i = MENUNUM(i); oldtitle = title; if (i == 0) /* Project */ { if (j == 0) /* Restart */ menumsg.command = PSCOMRESTART; else if (j == 1) /* Quit */ menumsg.command = PSCOMQUIT; } else if (i == 1) /* File */ { title = titlerunning; if (j == 0) /* Load font */ menumsg.command = PSCOMFILEF; else if (j == 1) /* Load file */ menumsg.command = PSCOMFILEL; else if (j == 2) /* Run file */ menumsg.command = PSCOMFILER; else if (j == 3) /* Interactive */ { menumsg.command = PSCOMINTER; title = titleinter; } } else if (i == 2) /* Control */ { if (j == 0) /* Pause every page */ { pause = !pause; if (pause) men2item0.Flags |= CHECKED; else men2item0.Flags &= ~CHECKED; break; } else if (j == 1) /* Continue after pause */ { menumsg.command = 0; title = savetitle; OffMenu(intwindow, 2 | SHIFTITEM(1)); } else if (j == 2) /* Interrupt */ { PSsignalint(arec, 1); break; } } else /* NULL */ break; OffMenu(intwindow, 0 | SHIFTITEM(NOITEM)); OffMenu(intwindow, 1 | SHIFTITEM(NOITEM)); if (title != oldtitle) SetWindowTitles(intwindow, NULL, (UBYTE *) title); menumsg.length = -1; menumsg.string = NULL; ReplyMsg((struct Message *) &menumsg); break; } ReplyMsg(msg); } /* Get next message */ for (;;) { msg = GetMsg(menuport); if (msg) break; WaitPort(menuport); } } /* Open failure or close. Reply remove our task */ end: Forbid(); ReplyMsg((struct Message *) &menumsg); menutask = NULL; RemTask(menutask); } /* Signal an interrupt */ void __saveds sigint() { PSsignalint(arec, 1); } /* Signal a floating point error */ void __saveds sigfpe() { PSsignalfpe(arec); } /* Call an external function (dummy) */ # ifdef STATICLINK int callextfunc(APTR func, APTR aptr, int parms) { return 0; } # endif /* Flush the page to the screen */ # ifdef STATICLINK void flushpage(int y1, int y2) # else void __saveds __asm flushpage(register __d0 int y1, register __d1 int y2) # endif { if (argscreen) { menumsg.y1 = y1; menumsg.y2 = y2; sendmenu(PSACTFLUSH); } } /* Copy the page to the output */ # ifdef STATICLINK void copypage(int num) # else void __saveds __asm copypage(register __d0 int num) # endif { ioerror = 0; if (argprint) while (num--) printpage(); if (argiff) iffpage(); if (argscreen) sendmenu(PSACTPAUSE); if (ioerror) PSerror(arec, ioerror); } /* Print the page */ void printpage() { ULONG sig; UWORD prflags; /* Disable break exceptions so we can wait on the signal instead */ SetExcept(0, SIGBREAKF_CTRL_C); breakset = 0; /* First check the printer is ready */ prreq.io_Command = PRD_QUERY; ((struct IOStdReq *) &prreq)->io_Data = (APTR) prstatus; if (DoIO((struct IORequest *) &prreq)) { ioerror = errioerror; return; } if (((struct IOStdReq *) &prreq)->io_Actual == 1 && prstatus[0] & 3 != 0) FPrintf(argint ? confh : errfh, "post: printer not ready (CTRL/C to abort)\n"); /* Now dump the page */ prrast.BitMap = &bitmap; prreq.io_Command = PRD_DUMPRPORT; prreq.io_RastPort = &prrast; prreq.io_ColorMap = (struct ColorMap *) &colormap; prreq.io_Modes = 0; prreq.io_SrcX = 0; prreq.io_SrcY = 0; prreq.io_SrcWidth = parm.page.xsize; prreq.io_SrcHeight = parm.page.ysize; prreq.io_Special = (SPECIAL_DENSITY1 * prden) | SPECIAL_TRUSTME; if (parm.page.ybase + parm.page.ysize >= parm.page.yheight) prreq.io_SrcHeight = parm.page.yheight - parm.page.ybase; else prreq.io_Special |= SPECIAL_NOFORMFEED; if (prextdata->ped_MaxXDots != 0) if (prreq.io_SrcWidth > prextdata->ped_MaxXDots) prreq.io_SrcWidth = prextdata->ped_MaxXDots; if (prextdata->ped_MaxYDots != 0) if (prreq.io_SrcHeight > prextdata->ped_MaxYDots) prreq.io_SrcHeight = prextdata->ped_MaxYDots; prreq.io_DestCols = prreq.io_SrcWidth; prreq.io_DestRows = prreq.io_SrcHeight; prflags = prprefs->PrintFlags; prprefs->PrintFlags = prflags & ~DIMENSIONS_MASK | IGNORE_DIMENSIONS; /* We use asynchronous IO so we can abort it with a CTRL/C */ SendIO((struct IORequest *) &prreq); for (;;) { sig = Wait(prsig | SIGBREAKF_CTRL_C); if (sig & SIGBREAKF_CTRL_C) { AbortIO((struct IORequest *) &prreq); WaitIO((struct IORequest *) &prreq); ioerror = errioerror; break; } if (GetMsg(prport)) break; } if (prreq.io_Error != 0) ioerror = errioerror; /* Restore break exceptions */ SetExcept(~0, SIGBREAKF_CTRL_C); breakset = 1; prprefs->PrintFlags = prflags; } /* IFF ILBM routines */ static int iffseq = 0; static int ifferr; static FILE *ifffptr; /* Put a byte */ static void iffputb(int b) { if (ifferr) return; if (putc((int) b, ifffptr) == EOF) { ifferr = 1; return; } } /* Put a word */ static void iffputw(int w) { iffputb(w>>8); iffputb(w); } /* Put a long */ static void iffputl(int l) { iffputb(l>>24); iffputb(l>>16); iffputb(l>>8); iffputb(l); } /* Put a string */ static void iffputs(char *str) { while (*str) iffputb(*str++); } /* Pack a bitmap row */ static void iffpack(char *buf, int len) { int b, c, l; if (ifferr) return; l = 0; while (len--) { b = *buf++; /* Pick up a byte */ c = 1; while (len && *buf == b && c < 128) { c++; buf++; len--; /* See if it begins a run */ } if (c == 2 && /* If a two byte run */ l > 0 && /* and preceeded by literals */ l <= 125 && /* and not more than 125 of them */ (len <= 2 || /* and no more than 2 bytes left */ *buf != *(buf + 1))) /* or not followed by a run */ { c = 1; /* Then make it a literal */ buf--; len++; } if (c == 1) /* If not a run */ { l++; /* Then it must be a literal */ c = 0; } if (l > 0 && /* If we have some literals */ (c > 1 || /* and beginning a run */ l == 127 || /* or reached 127 */ len == 0)) /* or no more bytes left */ { if (putc(l - 1, ifffptr) == EOF) { ifferr = 1; return; } while (l) /* Then write out the literals */ { if (putc(*(buf - c - l), ifffptr) == EOF) { ifferr = 1; return; } l--; } } if (c > 1) /* If we have a run, write it */ { if (putc(1 - c, ifffptr) == EOF) { ifferr = 1; return; } if (putc(b, ifffptr) == EOF) { ifferr = 1; return; } } } } /* Determine the current address */ static long ifftell(void) { long addr; if (ifferr) return 0; if ((addr = ftell(ifffptr)) == -1) { ifferr = 1; return 0; } return addr; } /* Fix up the length of a chunk */ static void ifffixup(long addr) { long size; if (ifferr) return; if ((size = ftell(ifffptr)) == -1) { ifferr = 1; return; } if (size & 1) iffputb(0); size = size - addr - 8; if (fseek(ifffptr, addr + 4, 0) != 0) { ifferr = 1; return; } iffputl(size); if (fseek(ifffptr, 0, 2) != 0) { ifferr = 1; return; } } /* Write the page to the iff output file */ void iffpage(void) { long addr1, addr2; int xa, ya; int i, j, k, ch; UWORD w; int fslen; char fname[110], fsnum[10]; /* Compute the aspect ratio. Make sure the values fit into a byte */ xa = parm.page.yden; ya = parm.page.xden; i = igcd(xa, ya); xa /= i; ya /= i; while (xa > 255 && ya > 255) { xa /= 2; ya /= 2; } /* Construct the file name. Copy it, replacing "*" by the sequence * number. The scan it backwards replacing "?" by digits */ iffseq++; fslen = 0; i = iffseq; while (i) { fsnum[fslen++] = i % 10 + '0'; i /= 10; } i = j = 0; for (;;) { if (j > 100) { ioerror = errioerror; return; } ch = argifn[i++]; if (ch == '*') { k = fslen; while (k--) fname[j++] = fsnum[k]; } else fname[j++] = ch; if (ch == 0) break; } k = 0; while (--j) { if (fname[j] == '?') fname[j] = (k < fslen) ? fsnum[k++] : '0'; } /* Open the file, write a FORM ILBM, and close it again */ ifferr = 0; ifffptr = fopen(fname, "wb"); if (ifffptr == NULL) ifferr = 1; addr1 = ifftell(); iffputs("FORM"); /* FORM ILBM */ iffputl(0); iffputs("ILBM"); iffputs("BMHD"); /* BMHD */ iffputl(20); iffputw(parm.page.xsize); /* Width */ iffputw(parm.page.ysize); /* Height */ iffputw(0); /* X position */ iffputw(0); /* Y position */ iffputb(parm.page.depth); /* Number of bit planes */ iffputb(0); /* Masking: None */ iffputb(1); /* Compression: ByteRun */ iffputb(0); /* Pad1 */ iffputw(0); /* Transparent colour */ iffputb(xa); /* X aspect */ iffputb(ya); /* Y aspect */ iffputw(parm.page.xsize); /* Source width */ iffputw(parm.page.ysize); /* Source height */ addr2 = ifftell(); iffputs("CMAP"); /* CMAP */ iffputl(0); for (i = 0; i < colormap.Count; i++) { w = ((UWORD *) colormap.ColorTable)[i]; iffputb(((w >> 8) & 15) << 4); iffputb(((w >> 4) & 15) << 4); iffputb(( w & 15) << 4); } ifffixup(addr2); if (argscreen) { iffputs("CAMG"); /* CAMG */ iffputl(4); iffputl(newscreen.ViewModes); } addr2 = ifftell(); iffputs("BODY"); /* BODY */ iffputl(0); for (j = 0; j < bitmap.Rows; j++) for (i = 0; i < bitmap.Depth; i++) iffpack((char *) bitmap.Planes[i] + j * bitmap.BytesPerRow, bitmap.BytesPerRow); ifffixup(addr2); ifffixup(addr1); if (fclose(ifffptr) == EOF) ifferr = 1; if (ifferr) ioerror = errioerror; } /* Find the greatest common divisor of two positive integers. If one is * zero the result is the other */ int igcd(int n, int m) { unsigned int n1, m1, r; if (n > m) { n1 = n; m1 = m; } else if (m > n) { n1 = m; m1 = n; } else return n; while (m1 != 0) { r = n1 % m1; n1 = m1; m1 = r; } return (int) n1; } /* End of file "post.c" */