home *** CD-ROM | disk | FTP | other *** search
/ ARM Club 3 / TheARMClub_PDCD3.iso / hensa / maths / plplot / plplot_2 / sys / amiga / src / plsupport. < prev   
Encoding:
Text File  |  1994-05-23  |  17.7 KB  |  719 lines

  1. /* $Id: plsupport.c,v 1.7 1994/05/23 22:12:00 mjl Exp $
  2.    $Log: plsupport.c,v $
  3.  * Revision 1.7  1994/05/23  22:12:00  mjl
  4.  * Minor incompatibilities with main sources fixed.
  5.  *
  6.  * Revision 1.6  1994/03/23  08:56:30  mjl
  7.  * Header file rearrangement.
  8.  *
  9.  * Revision 1.5  1993/07/01  21:59:55  mjl
  10.  * Changed all plplot source files to include plplotP.h (private) rather than
  11.  * plplot.h.  Rationalized namespace -- all externally-visible plplot functions
  12.  * now start with "pl"; device driver functions start with "plD_".
  13.  *
  14.  * Revision 1.4  1993/03/15  21:34:29  mjl
  15.  * Reorganization and update of Amiga drivers.  Window driver now uses Amiga
  16.  * OS 2.0 capabilities.
  17.  *
  18.  * Revision 1.3  1993/01/23  06:12:48  mjl
  19.  * Preliminary work on new graphical interface (2.04-specific) for the Amiga.
  20.  *
  21.  * Revision 1.2  1992/10/12  17:11:27  mjl
  22.  * Amiga-specific mods, including ANSI-fication.
  23.  *
  24.  * Revision 1.1  1992/05/20  21:35:29  furnish
  25.  * Initial checkin of the whole PLPLOT project.
  26.  *
  27. */
  28.  
  29. #include "plplotP.h"
  30. #include "plamiga.h"
  31.  
  32. #include <stdlib.h>
  33. #include <string.h>
  34. #include <exec/memory.h>
  35. #include <devices/printer.h>
  36. #include <devices/prtbase.h>
  37. #include <libraries/dosextens.h>
  38. #include <proto/exec.h>
  39.  
  40. /*----------------------------------------------------------------------*\
  41. * Bitmap builders
  42. \*----------------------------------------------------------------------*/
  43.  
  44. static struct BitMap Bitmap;
  45. static long bitmapx, bitmapy, wordsperrow;
  46. static short *bitmap;
  47.  
  48. /* Functions */
  49.  
  50. int  mapinit    (long, long);
  51. void mapline    (register int, register int, register int, register int);
  52. void mapfree    (void);
  53. void mapclear    (void);
  54.  
  55. /*----------------------------------------------------------------------*\
  56. * mapinit
  57. * Allocate bitmap.
  58. \*----------------------------------------------------------------------*/
  59.  
  60. int 
  61. mapinit(long bmapx, long bmapy)
  62. {
  63.     bitmapx = bmapx;
  64.     bitmapy = bmapy;
  65.     wordsperrow = (bmapx + 15) / 16;
  66.     Bitmap.BytesPerRow = wordsperrow * 2;
  67.     Bitmap.Rows = bmapy;
  68.     /* Allocate memory for bitmap */
  69.     if ((bitmap = (short *) calloc(wordsperrow * 2, (int) bmapy)) == NULL) {
  70.     fprintf(stderr, "\nCan't allocate memory for bitmap dump.\n");
  71.     return (1);
  72.     }
  73.     Bitmap.Planes[0] = (PLANEPTR) bitmap;
  74.     return (0);
  75. }
  76.  
  77. /*----------------------------------------------------------------------*\
  78. * mapline
  79. * Draw a line in the bitmap.
  80. \*----------------------------------------------------------------------*/
  81.  
  82. void 
  83. mapline(register int x1, register int y1, register int x2, register int y2)
  84. {
  85.     register short *p;
  86.     register unsigned int b;
  87.     register int t;
  88.     int d;
  89.     int nextrow;
  90.  
  91.     /* we always want to go left to right. */
  92.     if (x1 > x2) {
  93.     t = x1;
  94.     x1 = x2;
  95.     x2 = t;
  96.     t = y1;
  97.     y1 = y2;
  98.     y2 = t;
  99.     }
  100.     p = bitmap + y1 * wordsperrow;
  101.     /* we always want to go `up'. */
  102.     if (y2 > y1)
  103.     nextrow = wordsperrow;
  104.     else {
  105.     y2 = y1 * 2 - y2;
  106.     nextrow = -wordsperrow;
  107.     }
  108.     b = 1L << (15 - (x1 & 15));
  109.     p += (x1 >> 4);
  110.     x2 -= x1;
  111.     y2 -= y1;
  112.     /* two routines, one for major in x, one for major in y */
  113.     if (y2 > x2) {
  114.     d = y2;
  115.     t = x2 / 2;
  116.     y1 = y2;
  117.     while (y1 >= 0) {
  118.         *p |= b;
  119.         p += nextrow;
  120.         t += x2;
  121.         if (t >= d) {
  122.         t -= d;
  123.         b >>= 1;
  124.         if (b == 0) {
  125.             b = 0x8000;
  126.             p++;
  127.         }
  128.         }
  129.         y1--;
  130.     }
  131.     }
  132.     else {
  133.     d = x2;
  134.     t = y2 / 2;
  135.     x1 = x2;
  136.     while (x1 >= 0) {
  137.         *p |= b;
  138.         b >>= 1;
  139.         if (b == 0) {
  140.         b = 0x8000;
  141.         p++;
  142.         }
  143.         t += y2;
  144.         if (t >= d) {
  145.         t -= d;
  146.         p += nextrow;
  147.         }
  148.         x1--;
  149.     }
  150.     }
  151. }
  152.  
  153. /*----------------------------------------------------------------------*\
  154. * mapfree  -- deallocate bitmap.
  155. * mapclear -- 0-fill bitmap.
  156. \*----------------------------------------------------------------------*/
  157.  
  158. void 
  159. mapfree(void)
  160. {
  161.     free((VOID *) bitmap);
  162. }
  163.  
  164. void 
  165. mapclear(void)
  166. {
  167.     memset((char *) bitmap, '\0', (int) (wordsperrow * (long) bitmapy * 2));
  168. }
  169.  
  170. /*----------------------------------------------------------------------*\
  171. * Printer utility routines
  172. \*----------------------------------------------------------------------*/
  173.  
  174. static union printerIO {
  175.     struct IOStdReq ios;
  176.     struct IODRPReq iodrp;
  177.     struct IOPrtCmdReq iopc;
  178. } *printerIO;
  179.  
  180. static struct PrinterData *PD;
  181. static struct PrinterExtendedData *PED;
  182. static struct MsgPort *replyport;
  183. static struct RastPort rastport;
  184.  
  185. static short dummycolors[] =
  186. {0x0000, 0x0fff};
  187. static struct ColorMap dummyColorMap =
  188. {NULL, NULL, 2, (APTR) & dummycolors};
  189.  
  190. /* Functions */
  191.  
  192. static void doio    (void);
  193.  
  194. int  queryprint        (long *, long *, long *, long *, long *, long *);
  195. int  openprinter    (void);
  196. void closeprinter    (void);
  197. void ejectpage        (void);
  198. void dmpport        (long, int, int);
  199. void screendump        (PLINT);
  200.  
  201. /*----------------------------------------------------------------------*\
  202. * queryprint
  203. * Get preferences printer settings.
  204. \*----------------------------------------------------------------------*/
  205.  
  206. int 
  207. queryprint(long *bmapx, long *bmapy, long *bmapxmax, long *bmapymax, 
  208.        long *xdpi, long *ydpi)
  209. {
  210.     int mode;
  211.     Bitmap.BytesPerRow = 0;
  212.     Bitmap.Rows = 0;
  213.     Bitmap.Depth = 1;
  214.     rastport.BitMap = &Bitmap;
  215.     dmpport((long) (SPECIAL_NOPRINT), 0, 0);
  216.  
  217.     *bmapxmax = PED->ped_MaxXDots;
  218.     *bmapymax = 95 * PED->ped_YDotsInch / 10;    /* 9.5in to prevent problems */
  219.  
  220.     *xdpi = PED->ped_XDotsInch;
  221.     *ydpi = PED->ped_YDotsInch;
  222.  
  223.     if (PD->pd_Preferences.PrintFlags & BOUNDED_DIMENSIONS) {
  224.     *bmapx = PD->pd_Preferences.PrintMaxWidth * PED->ped_XDotsInch / 10;
  225.     *bmapy = PD->pd_Preferences.PrintMaxHeight * PED->ped_YDotsInch / 10;
  226.     mode = 1;
  227.     }
  228.     else if (PD->pd_Preferences.PrintFlags & ABSOLUTE_DIMENSIONS) {
  229.     *bmapx = PD->pd_Preferences.PrintMaxWidth * PED->ped_XDotsInch / 10;
  230.     *bmapy = PD->pd_Preferences.PrintMaxHeight * PED->ped_YDotsInch / 10;
  231.     mode = 0;
  232.     }
  233.     else if (PD->pd_Preferences.PrintFlags & PIXEL_DIMENSIONS) {
  234.     *bmapx = PD->pd_Preferences.PrintMaxWidth;
  235.     *bmapy = PD->pd_Preferences.PrintMaxHeight;
  236.     mode = 0;
  237.     }
  238.     else {
  239.     *bmapx = *bmapxmax;
  240.     *bmapy = *bmapymax;
  241.     mode = 1;
  242.     }
  243.  
  244.     PD->pd_Preferences.PrintImage = IMAGE_NEGATIVE;
  245.     PD->pd_Preferences.PrintShade = SHADE_BW;
  246.     PD->pd_Preferences.PrintThreshold = 7;
  247.     PD->pd_Preferences.PrintAspect = ASPECT_HORIZ;
  248.     PD->pd_Preferences.PrintFlags = INTEGER_SCALING;
  249.     return (mode);
  250. }
  251.  
  252. /*----------------------------------------------------------------------*\
  253. * openprinter
  254. * Set up for printer dump.
  255. \*----------------------------------------------------------------------*/
  256.  
  257. int 
  258. openprinter(void)
  259. {
  260.     replyport = (struct MsgPort *) CreatePort("PLPlot.PIO", 0L);
  261.     if (replyport == NULL) {
  262.     fprintf(stderr, "Couldn't open reply port for printer dump.\n");
  263.     return (1);
  264.     }
  265.  
  266.     printerIO = (union printerIO *)
  267.     AllocMem((long) sizeof(union printerIO),
  268.          (long) (MEMF_CLEAR | MEMF_PUBLIC));
  269.     if (printerIO == NULL) {
  270.     DeletePort(replyport);
  271.     fprintf(stderr, "Couldn't create IO request block for printer dump.\n");
  272.     return (1);
  273.     }
  274.     printerIO->ios.io_Message.mn_Node.ln_Type = NT_MESSAGE;
  275.     printerIO->ios.io_Message.mn_Length = sizeof(union printerIO);
  276.     printerIO->ios.io_Message.mn_ReplyPort = replyport;
  277.  
  278.     if (OpenDevice("printer.device", 0L, (struct IORequest *) printerIO, 0L) != NULL) {
  279.     FreeMem((VOID *) printerIO, (long) sizeof(union printerIO));
  280.     DeletePort(replyport);
  281.     fprintf(stderr, "Error opening printer device.\n");
  282.     return (1);
  283.     }
  284.  
  285.     PD = (struct PrinterData *) printerIO->iodrp.io_Device;
  286.     PED = &PD->pd_SegmentData->ps_PED;
  287.     return (0);
  288. }
  289.  
  290. /*----------------------------------------------------------------------*\
  291. * closeprinter -- Free resources used in printer dump.
  292. * ejectpage    -- Send a page eject command to printer.
  293. \*----------------------------------------------------------------------*/
  294.  
  295. void 
  296. closeprinter(void)
  297. {
  298.     CloseDevice((struct IORequest *) printerIO);
  299.     FreeMem((VOID *) printerIO, (long) sizeof(union printerIO));
  300.     DeletePort(replyport);
  301. }
  302.  
  303. void 
  304. ejectpage(void)
  305. {
  306.     printerIO->ios.io_Command = PRD_RAWWRITE;
  307.     printerIO->ios.io_Data = (APTR) "\014";
  308.     printerIO->ios.io_Length = 1;
  309.     doio();
  310. }
  311.  
  312. /*----------------------------------------------------------------------*\
  313. * doio
  314. * Send off an i/o request.
  315. \*----------------------------------------------------------------------*/
  316.  
  317. static void 
  318. doio(void)
  319. {
  320.     register struct IODRPReq *ioreq;
  321.  
  322.     ioreq = &printerIO->iodrp;
  323.     SendIO((struct IORequest *) ioreq);
  324.     while (1) {
  325.     if (GetMsg(replyport) == NULL)
  326.         Wait(1L << replyport->mp_SigBit);
  327.     else
  328.         break;
  329.     }
  330. }
  331.  
  332. /*----------------------------------------------------------------------*\
  333. * dmpport
  334. * Dump a bitmap to the printer.
  335. \*----------------------------------------------------------------------*/
  336.  
  337. void 
  338. dmpport(long flags, int x, int y)
  339. {
  340.     register struct IODRPReq *ioreq;
  341.  
  342.     ioreq = &printerIO->iodrp;
  343.     ioreq->io_Command = PRD_DUMPRPORT;
  344.     ioreq->io_RastPort = &rastport;
  345.     ioreq->io_ColorMap = &dummyColorMap;
  346.     ioreq->io_Modes = 0;
  347.     ioreq->io_SrcX = 0;
  348.     ioreq->io_SrcY = 0;
  349.     ioreq->io_SrcWidth = x;
  350.     ioreq->io_SrcHeight = y;
  351.     ioreq->io_DestCols = x;
  352.     ioreq->io_DestRows = y;
  353.     ioreq->io_Special = flags | SPECIAL_TRUSTME;
  354.     doio();
  355. }
  356.  
  357. /*----------------------------------------------------------------------*\
  358. * screendump
  359. *
  360. * If type = 0 dump the plplot window to the printer with full preferences
  361. * support, i.e. color, shading, threshold, etc.  Otherwise we override many
  362. * of the preferences selections, create a full page black and white bitmap
  363. * and dump it to the printer.
  364. \*----------------------------------------------------------------------*/
  365.  
  366. void 
  367. screendump(PLINT type)
  368. {
  369.     register struct IODRPReq *ioreq;
  370.     long bmapx, bmapy;
  371.     long dwidth, dheight;
  372.  
  373.     if (type != 0)        /* originally also had  && fbuffer == 0 */
  374.     return;
  375.     if (openprinter())        /* return if error */
  376.     return;
  377.  
  378.     ioreq = &printerIO->iodrp;
  379.  
  380. /* INDENT OFF */
  381.  
  382.     if (type == 0) {
  383.     ioreq->io_Command    = PRD_DUMPRPORT;
  384.     ioreq->io_RastPort    = pla->WRPort;
  385.     ioreq->io_ColorMap    = pla->screen->ViewPort.ColorMap;
  386.     ioreq->io_Modes        = pla->screen->ViewPort.Modes;
  387.     ioreq->io_SrcX        = pla->xoffset;
  388.     ioreq->io_SrcY        = pla->yoffset;
  389.     ioreq->io_SrcWidth    = pla->cur_width;
  390.     ioreq->io_SrcHeight    = pla->cur_height;
  391.     ioreq->io_DestCols    = 0;
  392.     ioreq->io_DestRows    = 0;
  393.     ioreq->io_Special    = SPECIAL_FULLROWS | SPECIAL_FULLCOLS |
  394.                               SPECIAL_TRUSTME;
  395. /* INDENT ON */
  396.  
  397.     doio();
  398.     }
  399. #if 0
  400.     else {
  401.  
  402. /* get bmapx and bmapy (the others are dummy variables) */
  403.  
  404.     queryprint(&bmapx, &bmapy, &dwidth, &dheight, &dwidth, &dheight);
  405.  
  406. /* Set up map */
  407.  
  408.     if (mapinit(bmapx, bmapy)) {
  409.         closeprinter();
  410.         return;
  411.     }
  412.  
  413.     dwidth = bmapx - 2;
  414.     dheight = bmapy - 2;
  415.  
  416. /* PUT PLOT BUFFER READ HERE */
  417. /* NEED TO CALL MAPLINE AS NECESSARY -- SEE OLD CODE */
  418.  
  419.     dmpport(0L, bmapx, bmapy);
  420.     mapfree();
  421.     }
  422. #endif
  423.     closeprinter();
  424. }
  425.  
  426. /*----------------------------------------------------------------------*\
  427. * IFF file manipulators
  428. \*----------------------------------------------------------------------*/
  429.  
  430. #define BADFLAGS    (SPRITES|VP_HIDE|GENLOCK_AUDIO|GENLOCK_VIDEO)
  431. #define FLAGMASK    (~BADFLAGS)
  432. #define CAMGMASK    (FLAGMASK & 0x0000FFFFL)
  433.  
  434. struct BitMapHeader {
  435.     UWORD w, h;
  436.     WORD x, y;
  437.     UBYTE nPlanes;
  438.     UBYTE masking;
  439.     UBYTE compression;
  440.     UBYTE pad1;
  441.     UWORD transparentColor;
  442.     UBYTE xAspect, yAspect;
  443.     WORD pageWidth, pageHeight;
  444. } bmhd;
  445.  
  446. /* Header for a B&W IFF image file. */
  447.  
  448. static struct iffhead {
  449.     char formname[4];
  450.     long formlen;        /* fill me in */
  451.     char ilbmname[4];
  452.     char bmhdname[4];
  453.     long bmhdlen;
  454.     short w, h;            /* fill me in */
  455.     long dummy0;
  456.     char numplanes, masking, compression, pad1;
  457.     short tc;
  458.     char xas, yas;
  459.     short pw, ph;
  460.     char cmapname[4];
  461.     long cmaplen;
  462.     unsigned char r0, g0, b0, r1, g1, b1;
  463.     char bodyname[4];
  464.     long bodylen;        /* fill me in */
  465. } iffhead = { {'F','O','R','M'}, 0, {'I','L','B','M'}, {'B','M','H','D'}, 20,
  466.       0, 0, 0, 1, 0, 1, 0, 0, 1, 1, 320, 200, {'C','M','A','P'}, 6, 240, 240,
  467.       240, 0, 0, 0, {'B','O','D','Y'}, 0 } ;
  468.  
  469. static long iffpos;
  470. static short curbyte;
  471. static short curcount;
  472. static short runcount;
  473. static FILE *OutFile;
  474.  
  475. char outchunk[256];
  476.  
  477. /* Function prototypes */
  478.  
  479. static void iffobyte    (register int);
  480. static void iffoutbyte    (register int);
  481. static void finishrow    (void);
  482.  
  483. void iffwritefile    (PLINT, PLINT, FILE *);
  484. int  saveiff        (char *);
  485.  
  486. /*----------------------------------------------------------------------*\
  487. * saveiff
  488. *
  489. * Writes out color bitmap.
  490. \*----------------------------------------------------------------------*/
  491.  
  492. int
  493. saveiff(char *filename)
  494. {
  495.     long int formlen = 0, formpos, bmhdlen, camglen, camgbod;
  496.     long int bodylen = 0, bodypos, cmaplen;
  497.     long int numcolors, rowlen, rowoff, coloff;
  498.     short int i, j, k;
  499.     UWORD *coltable;
  500.     UBYTE *byteptr, rgb[3];
  501.     struct BitMap *PLBitMap;
  502.     FILE *IFFFile;
  503.  
  504.     if ((IFFFile = fopen(filename, "w+")) == NULL) 
  505.     return (1);
  506.  
  507.     iffpos = 0;
  508.     curbyte = -1;
  509.     curcount = 0;
  510.     runcount = 0;
  511.     OutFile = IFFFile;
  512.  
  513.     bmhdlen = sizeof(struct BitMapHeader);
  514.     camglen = 4;
  515.     PLBitMap = &pla->screen->BitMap;
  516.  
  517.     fwrite("FORM", sizeof(char), 4, IFFFile);
  518.     formpos = ftell(IFFFile);
  519.     fwrite((char *) &formlen, sizeof(long), 1, IFFFile);
  520.  
  521.     fwrite("ILBM", sizeof(char), 4, IFFFile);
  522.     formlen += 4;
  523.  
  524.     fwrite("BMHD", sizeof(char), 4, IFFFile);
  525.     formlen += 4;
  526.     fwrite((char *) &bmhdlen, sizeof(long), 1, IFFFile);
  527.     formlen += 4;
  528.     bmhd.w = 16 * ((pla->cur_width + 15) / 16);
  529.     bmhd.h = pla->cur_height;
  530.     bmhd.x = pla->window->LeftEdge + pla->xoffset;
  531.     bmhd.y = pla->window->TopEdge + pla->yoffset;
  532.     bmhd.nPlanes = PLBitMap->Depth;
  533.     bmhd.masking = 0;
  534.     bmhd.compression = 1;
  535.     bmhd.pad1 = 0;
  536.     bmhd.transparentColor = 0;
  537.     bmhd.xAspect = 10;
  538.     bmhd.yAspect = 11;
  539.     bmhd.pageWidth = pla->screen->Width;
  540.     bmhd.pageHeight = pla->screen->Height;
  541.     fwrite((char *) &bmhd, bmhdlen, 1, IFFFile);
  542.     formlen += bmhdlen;
  543.  
  544.     fwrite("CAMG", sizeof(char), 4, IFFFile);
  545.     formlen += 4;
  546.     fwrite((char *) &camglen, sizeof(long), 1, IFFFile);
  547.     formlen += 4;
  548.     camgbod = pla->screen->ViewPort.Modes & CAMGMASK;
  549.     fwrite((char *) &camgbod, sizeof(long), 1, IFFFile);
  550.     formlen += 4;
  551.  
  552.     fwrite("CMAP", sizeof(char), 4, IFFFile);
  553.     formlen += 4;
  554.     numcolors = 1;
  555.     for (i = PLBitMap->Depth; i > 0; i--)
  556.     numcolors *= 2;
  557.     cmaplen = numcolors * 3;
  558.     fwrite((char *) &cmaplen, sizeof(long), 1, IFFFile);
  559.     formlen += 4;
  560.     coltable = (UWORD *) pla->CMap->ColorTable;
  561.     for (i = 0; i < numcolors; i++) {
  562.     rgb[0] = (*coltable >> 4) & 0xf0;
  563.     rgb[1] = *coltable & 0xf0;
  564.     rgb[2] = (*coltable << 4) & 0xf0;
  565.     fwrite((char *) rgb, sizeof(UBYTE), 3, IFFFile);
  566.     formlen += 3;
  567.     coltable++;
  568.     }
  569.  
  570.     fwrite("BODY", sizeof(char), 4, IFFFile);
  571.     formlen += 4;
  572.     bodypos = ftell(IFFFile);
  573.     fwrite((char *) &bodylen, sizeof(long), 1, IFFFile);
  574.     formlen += 4;
  575.     rowlen = ((pla->cur_width + 15) / 16);
  576.     rowlen *= 2;
  577.     rowoff = (pla->window->TopEdge + pla->yoffset) * PLBitMap->BytesPerRow;
  578.     coloff = (pla->window->LeftEdge + pla->xoffset) / 8;
  579.     for (i = 0; i < pla->cur_height; i++) {
  580.     for (j = 0; j < PLBitMap->Depth; j++) {
  581.         byteptr = (UBYTE *) PLBitMap->Planes[j] + rowoff + coloff;
  582.         for (k = 0; k < rowlen; k++)
  583.         iffoutbyte(*byteptr++ & 255);
  584.         finishrow();
  585.     }
  586.     rowoff += PLBitMap->BytesPerRow;
  587.     }
  588.     if (iffpos & 1)
  589.     iffobyte(0);
  590.     bodylen = iffpos;
  591.     formlen += iffpos;
  592.     fflush(IFFFile);
  593.     fseek(IFFFile, formpos, 0);
  594.     fwrite((char *) &formlen, sizeof(long), 1, IFFFile);
  595.     fseek(IFFFile, bodypos, 0);
  596.     fwrite((char *) &bodylen, sizeof(long), 1, IFFFile);
  597.     fclose(IFFFile);
  598.     return (0);
  599. }
  600.  
  601. /*----------------------------------------------------------------------*\
  602. * iffwritefile
  603. *
  604. * Writes out B&W bitmap.
  605. \*----------------------------------------------------------------------*/
  606.  
  607. void 
  608. iffwritefile(PLINT xdpi, PLINT ydpi, FILE *File)
  609. {
  610.     register int i, j;
  611.     register short *p;
  612.  
  613.     p = bitmap;
  614.     OutFile = File;
  615.     fwrite((char *) &iffhead, 1, sizeof(struct iffhead), OutFile);
  616.     iffpos = 0;
  617.     curbyte = -1;
  618.     curcount = 0;
  619.     runcount = 0;
  620.     for (j = 0; j < bitmapy; j++) {
  621.     for (i = wordsperrow; i; i--, p++) {
  622.         iffoutbyte((*p >> 8) & 255);
  623.         iffoutbyte(*p & 255);
  624.     }
  625.     finishrow();
  626.     }
  627.     if (iffpos & 1)
  628.     iffobyte(0);
  629.     fseek(OutFile, 0L, 0);
  630.     iffhead.w = bitmapx;
  631.     iffhead.h = bitmapy;
  632.     iffhead.pw = bitmapx;
  633.     iffhead.ph = bitmapy;
  634.     iffhead.formlen = iffpos + sizeof(struct iffhead) - 8;
  635.     iffhead.bodylen = iffpos;
  636.     iffhead.xas = xdpi;
  637.     iffhead.yas = ydpi;
  638.     fwrite((char *) &iffhead, 1, sizeof(struct iffhead), OutFile);
  639. }
  640.  
  641. /*----------------------------------------------------------------------*\
  642. * IFF utility routines
  643. \*----------------------------------------------------------------------*/
  644.  
  645. static void 
  646. iffobyte(register int b)
  647. {
  648.     putc(b, OutFile);
  649.     iffpos++;
  650. }
  651.  
  652. static void 
  653. iffoutbyte(register int b)
  654. {
  655.     register int i;
  656.  
  657.     if (b == curbyte && runcount < 125) {
  658.     runcount++;
  659.     }
  660.     else {
  661.     if (runcount > 2) {
  662.         if (curcount > 0) {
  663.         iffobyte(curcount - 1);
  664.         for (i = 0; i < curcount; i++)
  665.             iffobyte(outchunk[i]);
  666.         curcount = 0;
  667.         }
  668.         iffobyte(256 - runcount + 1);
  669.         iffobyte(curbyte);
  670.     }
  671.     else {
  672.         while (runcount > 0) {
  673.         outchunk[curcount++] = curbyte;
  674.         runcount--;
  675.         }
  676.         if (curcount > 110) {
  677.         iffobyte(curcount - 1);
  678.         for (i = 0; i < curcount; i++)
  679.             iffobyte(outchunk[i]);
  680.         curcount = 0;
  681.         }
  682.     }
  683.     curbyte = b;
  684.     runcount = 1;
  685.     }
  686. }
  687.  
  688. static void 
  689. finishrow(void)
  690. {
  691.     register int i;
  692.  
  693.     if (runcount <= 2) {
  694.     while (runcount > 0) {
  695.         outchunk[curcount++] = curbyte;
  696.         runcount--;
  697.     }
  698.     }
  699.     if (curcount > 0) {
  700.     iffobyte(curcount - 1);
  701.     for (i = 0; i < curcount; i++)
  702.         iffobyte(outchunk[i]);
  703.     curcount = 0;
  704.     }
  705.     if (runcount > 0) {
  706.     iffobyte(256 - runcount + 1);
  707.     iffobyte(curbyte);
  708.     curbyte = -1;
  709.     runcount = 0;
  710.     }
  711. }
  712.  
  713.