/* This file contains the output drivers for
                LaserJets, Epson, Vt100's and pc screens.
        If some kind sole would like to add LA100 etc, go right ahead,
                (you will have to modify DVITOBIT.C to call your
                extra dev_size_la100, and dev_print_la100 routines)

  Thanks to     Evan Wilson, N Z Dairy Group, for adding the sixel driver
                (for la100's la75's etc.)

*/
 
#if ( defined DJ || defined EMXOS2 )   /* a.r. */
#define unix
#endif

#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <assert.h>
#include "int32.h"

#ifdef DJ /* a.r. if Hartmut releases GRX for Linux replace DJ -> LINUX */
#  ifndef __linux__
#    include <pc.h>
#  endif
#  include <grx.h>
#  include <bccgrx.h>
#endif
#ifdef __TURBOC__
#  include <conio.h>
#  include <graphics.h>
#endif

#include "bmp.h"
#define false 0
#define true !false

char *bgidir();
int cmtobits(double *x, int *nx, double dpi);
int printstrd(char *s, int i);
int printstr(char *s);
extern int dev_hpplus,dev_vhires,dev_hires,bmp_compress,dev_lowmem,dev_low,iscolor;
extern int dev_noff,dev_nosquash,dev_wide,dev_noclip,dev_over,dev_noflip;
extern char outbitname[];

#ifdef __TURBOC__
dev_size_vt(int *nxbits, int *nybits, double *devxcm, double *devycm)
{
        *devxcm = 20;
        *devycm = 15;
        dev_noflip = true;
        dev_hires = true;
        if (dev_hires) {
                *nxbits = 400;
                *nybits = 400;
        } else {
                *nxbits = 70;
                *nybits = 50;
        }
}
dev_print_vt(Bitmap *b)
{
   int gdriver = DETECT, gmode, errorcode;
   int x,y,z;
   int white;
   char *line;
   initgraph(&gdriver, &gmode, bgidir());
   errorcode = graphresult();
   if (errorcode != grOk)  /* an error occurred */
   {
          printf("Graphics error: %s\n", grapherrormsg(errorcode));
          printf("Press any key to halt:");
          getch();
          exit(1);             /* return with error code */
   }

   white = getmaxcolor();
        for (y=0; y<b->ny; y++) {
          line = bmp_row(b,b->ny-y);
          setfillstyle(SOLID_FILL,getmaxcolor());
          for (x=0; x< b->nx ; x++) {
                z = 1 << (x % 8);
                if ((z & line[x/8]) != 0) {
                  if (dev_hires) {
                        putpixel(x,y,white);
                  } else {
                                bar(x*10,y*10,x*10+8,y*10+8);
                  }
                }
          }
        }

   /* clean up */
   getch();
   closegraph();
   return 0;
}
#elif DJ  /* a.r. if Hartmut releases GRX for Linux replace DJ -> LINUX */
dev_size_vt(int *nxbits, int *nybits, double *devxcm, double *devycm)
{
   int gdriver = DETECT, gmode, errorcode;
   int maxx,maxy;

        *devxcm = 20;
        *devycm = 15;
        dev_noflip = true;
        dev_hires = true;

   initgraph(&gdriver, &gmode, bgidir());
   errorcode = graphresult();
   if (errorcode != grOk) 
   {
          printf("Graphics error: %s\n", grapherrormsg(errorcode));
          printf("Press any key to halt:");
          getch();
          exit(1);
   }


        if (dev_hires) {
                *nxbits = getmaxx() /*1000*/;
                *nybits = getmaxy() /*1000*/;
        } else {
                *nxbits = 70;
                *nybits = 50;
        }
        closegraph();
}
dev_print_vt(Bitmap *b)
{
   int gdriver = DETECT, gmode, errorcode;
   int x,y,z;
   int white;
   char *line;
   initgraph(&gdriver, &gmode, bgidir());
   errorcode = graphresult();
   if (errorcode != grOk)  /* an error occurred */
   {
          printf("Graphics error: %s\n", grapherrormsg(errorcode));
          printf("Press any key to halt:");
          getch();
          exit(1);             /* return with error code */
   }

   white = 15 /*getmaxcolor()*/; /* a.r. 256 colors ... */
        for (y=0; y<b->ny; y++) {
          line = bmp_row(b,b->ny-y);
          setfillstyle(SOLID_FILL,getmaxcolor());
          for (x=0; x< b->nx ; x++) {
                z = 1 << (x % 8);
                if ((z & line[x/8]) != 0) {
                  if (dev_hires) {
                        putpixel(x,y,white);
                  } else {
                                bar(x*10,y*10,x*10+8,y*10+8);
                  }
                }
          }
        }

   /* clean up */
   getch();
   closegraph();
   return 0;
}
#else
dev_size_vt(int *nxbits, int *nybits, double *devxcm, double *devycm)
{
        *devxcm = 20;
        *devycm = 15;
        *nxbits = 76;
        *nybits = 22;
}
dev_print_vt(Bitmap *b)
{
   int x,y,z;
   char *line;

        for (y=0; y<b->ny; y++) {
          line = bmp_row(b,b->ny-y);
          for (x=0; x<b->nx ; x++) {
                z = 1 << (x % 8);
                if ((z & line[x/8]) != 0) {
                        printf("#");
                } else printf(" ");
          }
          printf("[%d]\n",b->ny-y);
        }
}
#endif

dev_print_sx(Bitmap *b)
{
                static unsigned char *out_buff;
                unsigned char *line;
                int nny, x, y, ly, r, z, nout;
                char *c, *o, buff[8];

                out_buff = (ucharp) malloc(b->nx);
                if (out_buff==NULL) {
                                printf("Memory allocation failure for outbuff \n");
                                exit(1);
                }
                if (dev_vhires) {
                        printstr ("\x1bP;;2q\"1;1");        /* Graphics mode very high res /
                } else if (dev_hires) {
                        printstr ("\x1bP;;5q\"1;1");        /* Graphics mode high res */
                } else {
                        printstr ("\x1bP;;10q\"1;1");       /* Graphics mode low res */
                }
                nny = ((b->ny-1)/6+1)*6;
                for (ly=nny-6; ly>=0; ly-=6) {          /* Step down 6 rows at a time */
                        for (x=0; x<b->nx; x++) out_buff[x] = 0;    /* Zero output array */
                        for (r=0,y=ly; r<6; y++,r++) {      /* Step up 1 row at a time */
                                if (y<b->ny) {
                                        line = (ucharp) bmp_row(b,y);
                                        for (x=0; x<b->nx; x++) {
                                                z = 1 << (x % 8);
                                                if ((z & line[x/8]) == 0) {
                                                        out_buff[x] |= 1 << (5 - r);
                                                }
                                        }
                                }
                        }
                        for (nout=(b->nx); out_buff[nout-1]==0 && nout>0; nout--);  /* Remo/
                        if (nout > 0) {
                                c = &out_buff[0];
                                o = &out_buff[0];
                                for (x=0; x<nout; x++) {                /* Step through the lin/
                                        out_buff[x] += 0x3f;                /* Add sixel format off/
                                        if (out_buff[x] != *c) {
                                                if (&out_buff[x]-c > 5) {   /* > 5 repeats, output comp/
                                                        sprintf (buff, "!%d%c", &out_buff[x]-c, *c);
                                                        for (r=0; buff[r]!=0; r++) *o++ = buff[r];
                                                } else {
                                                        for (r=0; r<&out_buff[x]-c; r++) *o++ = *c;
                                                }
                                                c = &out_buff[x];
                                        }
                                }
                                for (r=0; r<=&out_buff[nout]-c; r++) *o++ = *c;
                                nout = o - out_buff;
                                printmem (out_buff, nout);
                        }
                        printstr ("-");                     /* Graphics new line */
                }
                printstr ("\x1b\\\n");                  /* Graphics mode terminator */
#if ( defined __TURBOC__ || defined DJ || defined EMXOS2 )
                /* vax print symbiont adds a FF character itself */
                if (!dev_noff) printstr("\x0c"); /* form feed, reset origin */
#endif
}



dev_size_sx(int *nxbits, int *nybits, double *devxcm, double *devycm)
{
                if (dev_wide) {
                                if (!dev_nosquash && *devxcm>33) *devxcm = 33;
                } else {
                                if (!dev_nosquash && *devycm>29) *devycm = 29;
                                if (!dev_nosquash && *devxcm>20) *devxcm = 20;
                }
                if (dev_vhires) {
                                cmtobits(devxcm,nxbits,360);
                                cmtobits(devycm,nybits,360);
                } else if (dev_hires) {
                                cmtobits(devxcm,nxbits,144);
                                cmtobits(devycm,nybits,144);
                } else {
                                cmtobits(devxcm,nxbits,72);
                                cmtobits(devycm,nybits,72);
                }
}


dev_size_lj(int *nxbits, int *nybits, double *devxcm, double *devycm)
{
        if (dev_wide) {
                if (!dev_nosquash && *devxcm>28) *devxcm = 28;
        } else {
                if (!dev_nosquash && *devycm>27) *devycm = 27;
                if (!dev_nosquash && *devxcm>19) *devxcm = 19;
        }
        if (dev_lowmem) {
                *devxcm = 16;
                *devycm = 12;
        }
        if (dev_hires) {
                cmtobits(devxcm,nxbits,300);
                cmtobits(devycm,nybits,300);
        } else {
                cmtobits(devxcm,nxbits,150);
                cmtobits(devycm,nybits,150);
        }
}

int ljsendline(char *s, int nc, int y);
dev_print_lj(Bitmap *b)
{
        int x,y,nout;
        static unsigned char *out_buff;
        char pbuff[80];
        unsigned char swapbit[257];
        unsigned char swapnib[16]={0,8,4,12,2,10,6,14,1,9,5,13,3,11,7,15};
        unsigned char *o,c,*line;
        int nc,i,n1,n2;

        out_buff = (ucharp) malloc(b->nx + 10);
        if (out_buff==NULL) {
                printf("Memory allocation failure for outbuff \n");
                exit(1);
        }
        for (i=0;i<256;i++) {
                n1 = i & 0xf;
                n2 = (i >> 4) & 0xf;
                swapbit[i] = swapnib[n2] | (swapnib[n1] << 4);
        }
        for (i=0;i<256;i++) swapbit[i] = 255-swapbit[i]; /* invert */

        if (!dev_noff)  printstrd("%cE",27);    /* reset  */
        if (dev_hires) printstr("\x1b*t300R");  /* set resolution */
        else           printstr("\x1b*t150R");
        if (dev_hpplus)  printstr("\x1b*b1M");  /* compact */
        printstr("\x1b*r1A");           /* start graphics at cur pos */
        for (y=(b->ny-1); y>=0; y--) {
          line = (ucharp) bmp_row(b,y);
          for (nout=(b->nx/8+1); line[nout-1]==255 && nout>0; nout--);
          o = &out_buff[0];
          for (x=0; x<nout; x++) {
                  c = line[x];
                  nc = 0;
                  if (dev_hpplus) {
                  for (;x<nout-1 && line[x+1]==c && nc<250; x++) nc++;
                  *o++ = nc;
                  }
                  *o++ = swapbit[c];
          }
          ljsendline((char *) out_buff,o-out_buff,y);
        }
        printstr("\x1b*rB");        /* end graphics */
#if ( defined __TURBOC__ || defined DJ || defined EMXOS2 )
        /* vax print symbiont adds a FF character itself */
        if (!dev_noff) printstr("\x0c"); /* form feed, reset origin */
#endif
}
ljsendline(char *s, int nc,int y)
{
        printstrd("\x1b*b%dW",nc);  /* send nc bytes */
        printmem(s,nc);
}
printstrd(char *s, int i)
{
        static char pbuff[128];
        sprintf(pbuff,s,i);
        printmem(pbuff,strlen(pbuff));
}
printstr(char *s)
{
        printmem(s,strlen(s));
}

dev_size_pj(int *nxbits, int *nybits, double *devxcm, double *devycm)
{
        if (dev_wide) {
                if (!dev_nosquash && *devxcm>28) *devxcm = 28;
        } else {
                if (!dev_nosquash && *devycm>27) *devycm = 27;
                if (!dev_nosquash && *devxcm>19) *devxcm = 19;
        }
        iscolor = true;
        if (dev_hires) {
                cmtobits(devxcm,nxbits,180);
                cmtobits(devycm,nybits,180);
        } else {
                cmtobits(devxcm,nxbits,90);
                cmtobits(devycm,nybits,90);
        }
}
cmtobits(double *x, int *nx, double dpi)
{
        *nx = (int) dpi*(*x / 2.54);
        *nx = *nx/8;
        *nx = *nx*8+8;
           (*nx)--;
        *x = (*nx/dpi)*2.54;
}
int pjsendline(char *s, int nc, int y, int plane);
dev_print_pj(Bitmap *b)
{
        int x,y,nout;
        static unsigned char *out_buff, *out_buff2;
        static unsigned char *out_buffp0, *out_buffp1, *out_buffp2;
        char pbuff[80];
        unsigned char swapbit[257];
        unsigned char swapnib[16]={0,8,4,12,2,10,6,14,1,9,5,13,3,11,7,15};
        unsigned char *o,c,*line;
        int nc,i,n1,n2,plane;

        out_buff = (ucharp) malloc(b->nx + 10);
        out_buffp0 = (ucharp)  malloc(b->nx + 10);
        out_buffp1 = (ucharp) malloc(b->nx + 10);
        out_buffp2 = (ucharp) malloc(b->nx + 10);
        if (out_buff==NULL || out_buffp2==NULL) {
                printf("Memory allocation failure for outbuff \n");
                exit(1);
        }
        for (i=0;i<256;i++) {
                n1 = i & 0xf;
                n2 = (i >> 4) & 0xf;
                swapbit[i] = swapnib[n2] | (swapnib[n1] << 4);
        }
/*  for (i=0;i<256;i++) swapbit[i] = 255-swapbit[i];  invert */



        if (!dev_noff)  printstrd("%cE",27);    /* reset  */
        if (dev_over) printstrd("%c&k3W",27); /* transparency mode */
        if (dev_hires) printstr("\x1b*t180R");  /* set resolution */
        else           printstr("\x1b*t90R");
        if (dev_hpplus)  printstr("\x1b*b1M");  /* compact */

        printstr("\x1b*r3U");   /* use 3 color planes, 8 colors*/
        printstrd("\x1b*r%dS",b->nx); /* set width of image */
        printstr("\x1b*r1A");           /* start graphics at cur pos */


        for (y=(b->ny-1); y>=0; y--) {
          line = (ucharp) bmp_row(b,y);
          nout = b->nx/8;
          for (x=0; x<=b->nx/8; x++) {  /* extract one plane of bits */
                  for (plane = 0; plane < 3; plane++) {
                c = bitplane(line,x,plane);
                switch (plane) {
                  case 0:
                        out_buffp0[x] = c; break;
                  case 1:
                        out_buffp1[x] = c; break;
                  case 2:
                        out_buffp2[x] = c; break;
                }
                  }
          }

          for (plane = 0; plane < 3; plane++) {
                switch (plane) {
                  case 0:
                out_buff2 = out_buffp0;
                break;
                  case 1:
                out_buff2 = out_buffp1;
                break;
                  case 2:
                out_buff2 = out_buffp2;
                break;
                }
                o = &out_buff[0];
                for (x=0; x<=nout; x++) {
                  c = out_buff2[x];
                  nc = 0;
                  if (dev_hpplus) {  /* compress if requested */
                  for (;x<nout-1 && out_buff2[x+1]==c && nc<250; x++) nc++;
                  *o++ = nc;
                  }
                  *o++ = swapbit[c];
                }

                pjsendline((char *) out_buff,o-out_buff,y,plane);
          }
        }
        printstr("\x1b*rB");        /* end graphics */
#if ( defined __TURBOC__ || defined DJ || defined EMXOS2 )
        /* vax print symbiont adds a FF character itself */
        if (!dev_noff) printstr("\x0c"); /* form feed, reset origin */
#endif
}
int pjsendline(char *s, int nc,int y,int plane)
{
        int x;

        if (plane==2)   printstrd("\x1b*b%dW",nc);  /* send nc bytes */
        else        printstrd("\x1b*b%dV",nc);  /* send nc bytes */
        printmem(s,nc);
}

bitplane(char line[],int x, int p)
{
        /* x is byte count */
        /* construct a byte from line[x].hi.low.p  ... line[x+7] */
        register xx,i,curbit,c,pm;
        c = 0;
        x = x*8;
        pm = 1 << p;
        curbit = 1;
        for (xx=x; xx<x+8; xx++) {
                i = line[xx/2];
                if (xx % 2==0) i = (i & 0xf0)>>4;
                else i = i & 0xf;
                i = i & pm;
                if (i!=0) c = c + curbit;
                curbit = curbit << 1;
        }
        return c;
}


dev_size_ep(int *nxbits, int *nybits, double *devxcm, double *devycm)
{
        if (dev_wide) {
                if (!dev_nosquash && *devxcm>28) *devxcm = 28;
        } else {
                if (!dev_nosquash && *devycm>27) *devycm = 27;
                if (!dev_nosquash && *devxcm>19) *devxcm = 19;
        }
        if (dev_hires) {
                cmtobits(devxcm,nxbits,180);
                cmtobits(devycm,nybits,180);
        } else {
                cmtobits(devxcm,nxbits,120);
                cmtobits(devycm,nybits,72);
        }
}

dev_print_ep(Bitmap *b)
{
        int nny,x,y,nout;
        static unsigned char *out_buff;
        char pbuff[80];
        unsigned char *o,c,*line;
        int nc,i,n1,n2,r,z;

        if (dev_hires) {
                dev_print_ep24(b);
                return;
        }
        out_buff = (ucharp) malloc(b->nx + 10);
        if (out_buff==NULL) {
                printf("Memory allocation failure for outbuff \n");
                exit(1);
        }
        nny = b->ny;
        if (8*(nny/8) != nny) nny = (1+(nny/8))*8;
        for (y=nny-8 ; y>=0 ; y-=16) {
                for (r=0;r<(b->nx+5);r++) out_buff[r] = 0; /* zero array */
                for (r=0; r<8 ; r++,y++) {  /* for each of 8 columns */
                        line = (ucharp) bmp_row(b,y);
                        if (b->ny>=y) {
                        for (x=0; x<b->nx;x++) {
                                z = 1 << (x % 8);
                                if ((z & line[x/8]) == 0) {
                                         out_buff[x] |= 1 << r;
                                }
                        }}
                }
                for (nout=(b->nx); out_buff[nout-1]==0 && nout>0; nout--);
                epsendline(out_buff,nout);
        }
#if ( defined __TURBOC__ || defined DJ || defined EMXOS2 )
        /* vax print symbiont adds a FF character itself */
        if (!dev_noff) printstr("\x0c"); /* form feed, reset origin */
#endif
}
epsendline(char *s, int nc)
{
        char buff[20];
        strcpy(buff,"\x1bL");
        buff[2] = (nc) & 255;
        buff[3] = (nc) / 256;
        printmem(buff,4);
        printmem(s,nc);
        printstr("\x0d\x1bJ\x18");
}

ep24sendline(char *s, int nc)
{
        char buff[20];
        strcpy(buff,"\x1b*\x27");
        nc = nc / 3 + 1;
        buff[3] = (nc) & 255;
        buff[4] = (nc) / 256;
        printmem(buff,5);
        printmem(s,nc*3);
        printstr("\x0d\x1bJ\x18");
}
dev_print_ep24(Bitmap *b)
{
        int x,y,nout;
        static unsigned char *out_buff;
        char pbuff[80];
        unsigned char *o,c,*line;
        int nc,i,n1,n2,r,z,nny;

        out_buff = (ucharp) malloc(3*b->nx + 20);
        if (out_buff==NULL) {
                printf("Memory allocation failure for outbuff \n");
                exit(1);
        }
        nny = b->ny;
        if (24*(nny/24) != nny) nny = (1+(nny/24))*24;
        for (y=nny-24 ; y>=0 ; y-=48) {
                /* printf("y=%d\n",y); */
                for (r=0;r<(b->nx*3+5);r++) out_buff[r] = 0; /* zero array */
                for (r=0; r<24; r++,y++) {  /* for each of 8 columns */
                        line = (ucharp) bmp_row(b,y);
                        if (b->ny>=y) {
                        for (x=0; x<b->nx; x++) {
                                z = 1 << (x % 8);
                                if ((z & line[x/8]) == 0) {
                                        if (r<8) {
                                                 out_buff[x*3+2] |= 1 << r;
                                        } else if (r<16) {
                                                 out_buff[x*3+1] |= 1 << (r-8);
                                        } else {
                                                 out_buff[x*3+0] |= 1 << (r-16);
                                        }
                                }
                        }}
                }
                for (nout=(3*b->nx); out_buff[nout-1]==0 && nout>0; nout--);
                ep24sendline((char *)out_buff,nout);
        }
#if ( defined __TURBOC__ || defined DJ || defined EMXOS2 )
        /* vax print symbiont adds a FF character itself */
        if (!dev_noff) printstr("\x0c"); /* form feed, reset origin */
#endif
}

/* Word Perfect, tiff generation */

extern int fittobit;
dev_size_wp(int *nxbits, int *nybits, double *devxcm, double *devycm)
{
        *devxcm = 24;
        *devycm = 24;
        *nxbits = 200;
        *nybits = 200;
        fittobit = true;
}

#if ( defined DJ || defined EMXOS2 || defined EMXOS2 )   /* a.r. */
 #undef unix
#endif

#ifndef unix
/* tiff stuff starts here */

int32 sa(int32 a);
int32 ss(char *s);
int32 sw(int x);
int32 sl(int32 x);
int32 read_eps(char *fname,FILE *tf);
int sendmem(char *s, int32 j);
int setl(int32 p, int32 x);
int setw(int32 p, int x);

int32 tcnt; /* current byte position */
extern FILE *outbit;
FILE *tf;
int addeps=true;
int32 tstart;

dev_print_wp(Bitmap *b)
{
        /* 1=byte, 2=ascii, 3=short, 4=int32, 5=rational */
        char fname[80];
        int32 strip1,entrycount,stripoffsets,stripbcounts,ifd;
        int32 datep,datelen,namep,namelen,i,j;
        int32 h_ps,h_pslen,h_tiff,h_tifflen;

        tf = outbit; /* output file handle */

        if (addeps) {
                sw(0xd0c5); sw(0xc6d3);
                h_ps = sl(0);
                h_pslen = sl(0);
                sl(0); sl(0);
                h_tiff = sl(0);
                h_tifflen = sl(0);
                sw(0xffff);

                setl(h_ps,sa(tcnt));
                i = tcnt;
                tcnt += read_eps(outbitname,tf);
                setl(h_pslen,tcnt-i);
        }


        tstart = sw(0x4949); /* byte order  4d 4d */
        sw(0x002a);
        ifd = sl(0x0000);
        entrycount = sw(0);
        setl(ifd,sa(entrycount));
        sw(0xff); sw(3); sl(1); sw(1);  sw(0);      /* subfiletype */
        sw(0x100); sw(3); sl(1); sl(b->nx);     /* image width */
        sw(0x101); sw(3); sl(1); sl(b->ny);         /* image length */
        sw(0x102); sw(3); sl(1); sw(1); sw(0);  /* bits per sample */
        sw(0x103); sw(3); sl(1); sw(1); sw(0);  /* no compression */
        sw(0x106); sw(3); sl(1); sw(1); sw(0);  /* black and white */
        sw(0x111); sw(4); sl(1); stripoffsets = sl(0); /* offsets to image data */
        sw(0x11c); sw(3); sl(1); sw(1); sw(0); /* planar config */
        sw(0x131); sw(2); namelen = sl(1); namep = sl(0); /* Name  */
        sl(0); /* end of table  */
        setw(entrycount,9);
        strip1 = tcnt;
        send_image(b);
        setl(stripoffsets,sa(strip1));

        namelen = strlen("GLE Tiff output.");
        setl(namep,sa(ss("GLE Tiff output.")));

        if (addeps) {
                setl(h_tiff,tstart);
                setl(h_tifflen,tcnt-tstart);
        }

        fclose(tf);

}
send_image(Bitmap *b)
{
        int y;
        unsigned char swapnib[16]={0,8,4,12,2,10,6,14,1,9,5,13,3,11,7,15};
        unsigned char swapbit[257];
        unsigned char savechar,temp;
        static unsigned char *out_buff;
        unsigned int r,i,j,newy,x,z;
        unsigned char *line;
        unsigned char *o,c;
        int n1,n2;

        if (out_buff==0) out_buff = (ucharp) malloc(b->nx + 10);
        if (out_buff==NULL) {
                printf("Memory allocation failure for outbuff \n");
                exit(1);
        }
        for (i=0;i<256;i++) {
                n1 = i & 0xf;
                n2 = (i >> 4) & 0xf;
                swapbit[i] = swapnib[n2] | (swapnib[n1] << 4);
        }

        for (y=b->ny-1 ; y>=0 ; y-=1) {
                out_buff[0] = 0;
                line = (ucharp) bmp_row(b,y);
                for (i=0; i<b->nx/8; i++) {
                        out_buff[i] = swapbit[line[i]];
                }

                sendmem((char *) out_buff,b->nx/8);
        }
}


int32 sa(int32 a)
{
        return a-tstart;
}
int32 sw(int x)
{
        fwrite(&x,2,1,tf);
        tcnt += 2;
        return tcnt-2;
}
int32 ss(char *s)
{
        int i;

        i = strlen(s)+1;
        if (i&1 == 1) i++;
        fwrite(s,1,i,tf);
        tcnt += i;
        return tcnt-i;
}
sendmem(char *s, int32 j)
{
        fwrite(s,1,j,tf);
        tcnt += j;
}
int32 sl(int32 x)
{
        fwrite(&x,4,1,tf);
        tcnt += 4;
        return tcnt-4;
}
setl(int32 p, int32 x)
{
        if (fseek(tf,p,SEEK_SET)!=0)  printf("Seekl failed, %ld %ld\n",p,tcnt);
        fwrite(&x,4,1,tf);
        if (fseek(tf,tcnt,SEEK_SET)!=0) printf("Seekl eof failed, %ld \n",p);
}
setw(int32 p, int x)
{
        if (fseek(tf,p,SEEK_SET)!=0) printf("Seekw failed, %ld  %ld\n",p,tcnt);
        fwrite(&x,2,1,tf);
        if (fseek(tf,tcnt,SEEK_SET)!=0) printf("Seekw eof failed, %ld \n",p);
}

int32 read_eps(char *fname,FILE *tf)
{
        FILE *eps;
        static char buff[1002];
        char *s;
        int32 tot=0;
        int n;

        strcpy(buff,fname);
        s = strchr(buff,'.');
        if (s!=NULL) *s = 0;
        strcat(buff,".eps");

        eps = fopen(buff,"rb");
        if (eps==NULL) {
                printf("Unable to open {%s}, you must PSGLE /EPS first\n",buff);
                abort();
        }

        for (;!feof(eps);) {
          n = fread(buff,1,1000,eps);
          if (n>0) {
                fwrite(buff,1,n,tf);
                tot += n;
          }
        }
        buff[0] = 13; buff[1] = 10; buff[2] = 0;
        if (tot&1 == 1) {fwrite(" ",1,1,tf); tot++;}
        fwrite(buff,1,2,tf); tot+=2;
        return tot;
}
#else
dev_print_wp(Bitmap *b){}
#endif



dev_size_ec(int *nxbits, int *nybits, double *devxcm, double *devycm)
{
        if (dev_wide) {
                if (!dev_nosquash && *devxcm>28) *devxcm = 28;
        } else {
                if (!dev_nosquash && *devycm>27) *devycm = 27;
                if (!dev_nosquash && *devxcm>19) *devxcm = 19;
        }
        iscolor = true;
        if (dev_hires) {
                cmtobits(devxcm,nxbits,180);
                cmtobits(devycm,nybits,180);
        } else {
                cmtobits(devxcm,nxbits,120);
                cmtobits(devycm,nybits,72);
        }
        (*nxbits)++;
        (*nybits)++;
        printf("size %d %d \n",*nxbits,*nybits);
}
int epsendcol(char *s, int nc, int col);
int onecolor(char line[],char out[], int col, int nx);

static int y_line;
dev_print_ec(Bitmap *b)
{
        int x,y,nout;
        static unsigned char *outbuff;
        char pbuff[80];
        unsigned char *o,c,*line,*zline;
        int k,nc,i,n1,n2,plane,thiscol;
        int nny,r,z,zzy;

        outbuff = (ucharp) malloc(b->nx + 15);
        line = (ucharp) malloc(b->nx + 15);
        if (outbuff==NULL || line==NULL) {
                printf("Memory allocation failure for outbuff \n");
                exit(1);
        }


        nny = b->ny;
        if (8*(nny/8) != nny) nny = (1+(nny/8))*8;
        for (y=nny-8 ; y>=0 ; y-=16) {
                zzy = y;
                for (thiscol = 0; thiscol<9; thiscol ++) {
                        y = zzy;
                        for (r=0;r<(b->nx+10);r++) outbuff[r] = 0; /* zero array */
                        for (r=0; r<8 ; r++,y++) {  /* for each of 8 rows (pins)  */
                                zline = (ucharp) bmp_row(b,y);
                                if (y<=b->ny) {
                                 if (onecolor(zline,line,thiscol,b->nx)) {
                                        for (x=0; x<b->nx;x++) {
                                                z = 1 << (x % 8);
                                                if ((z & line[x/8]) != 0) {
                                                        outbuff[x] |= 1 << r;
                                                }
                                        }
                                 }
                                }
                        }
                y_line = y;
                        epsendcol(outbuff,b->nx,thiscol);
                }
                printstr("\x0d\x1bJ\x18");
        }
#if ( defined __TURBOC__ || defined DJ || defined EMXOS2 )
        /* vax print symbiont adds a FF character itself */
        if (!dev_noff) printstr("\x0c"); /* form feed, reset origin */
#endif
}
int ecol[]={0,1,6,4,2,3,5,0,0,0,0,0,0,0,0,0,0,0,0};
int epsendcol(char *s, int nc, int col)
{
        char buff[20];
        int x;

        for (; s[nc-1]==0 && nc>0; nc--);   /* Don't send trailing blanks */
        if (nc==0) return;
        printf("(%d)",y_line);

        sprintf(buff,"\x1br%d\x1bL",ecol[col]);
        buff[5] = (nc) & 255;
        buff[6] = (nc) / 256;
        printmem(buff,7);
        printmem(s,nc);
        printstr("\x0d");
}


int onecolor(char line[],char *out, int col, int nx)
{
        /* Extract a line of color=col, if blank then return false */
        register b,xx,r,c;
        char *outbf=out;
        int i,curbit;
        int nb = nx/8;

        r = false;

        for (i=0; i<nb; i++) {
                curbit = 1;
                c = 0;
                for (xx=i*8; xx<(i*8+8); xx++) {
                        b = line[xx/2];
                        if (xx % 2 == 0) b = (b & 0xf0)>>4;
                        else b = b & 0xf;
                        if (b==col) {
                                r = true;
                                c = c + curbit;
                        }
                        curbit = curbit << 1;
                }
                *outbf = c; outbf++;
        }
        return r;
}


