/**************************************************************************************\
*                             Apple Lisa 2 Emulator                                    *
*                  Internal Project Name:  Mona Lisa Overdrive                         *
*                  [ name will be changed upon final release ]                         *
*                                                                                      *
*                  Copyright (C) 1998 Ray Arsen Arachelian                             *
*                            All Rights Reserved                                       *
*                                                                                      *
****************************************************************************************
*                                                                                      *
*                       Apple ImageWriter I Emulator.                                  *
*                  Copyright (C) 1998 Ray A. Arachelian                                *
*                            All Rights Reserved                                       *
*                                                                                      *
*       Apple, the Apple logo, Lisa, Macintosh, and ImageWriter are trademarks of      *
*           Apple Computer, Inc., registered in the U.S. and other countries.          *
*                                                                                      *
*  PostScript is a trademark of Adobe Systems Incorporated which may be registered in  *
*                            certain juristictions.                                    *
*                                                                                      *
*  All other names mentioned herein may or may not be registered or unregistered       *
*                  trademarks held by their respective owners.                         *
*                                                                                      *
*       Thanks to: Frank M. Siegert for the help with the PostScript output            *
****************************************************************************************
*                                                                                      *
*   This program emulates an ImageWriter I printer and decodes all printed text and    *
*   graphics to a grayscale bit-mapped array which can then be later encoded as an     *
*   image or be transformed into another printer language such as Adobe(tm) Postscript *
*   or HP's HPCL or HPGCL.                                                             *
*                                                                                      *
*            Released under the terms of the GNU Public License version 2.0            *
*                                                                                      *
\**************************************************************************************/

//define BORDER 1
//define DEBUGX 1
//define STANDALONE 1                    // define this for a standalone program, else this can be compiled to a library.
#define INLISAEM   1                     // define this for a library

#define POSTSCRIPT 1
#define PCL        1
//#define XLIB       1

#ifdef INLISAEM
#define ARGV XLisaEm_Args.argv
#define ARGC XLisaEm_Args.argc
#else
#define ARGV argv
#define ARGC argc
#endif


#ifndef INLISAEM
#define VERSION "V0.8.1Beta"
#endif




#ifdef XLIB
//ifndef INLISAEM
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xos.h>
#include <X11/Xatom.h>
#include "icon_bitmap"
#endif

#define BITMAPDEPTH 1
#define TOO_SMALL 0
#define BIG_ENOUGH 1

#ifdef STANDALONE
#include <stdio.h>
#endif

#ifdef INLISAEM
#define NO_IW_H_INC 1
#define INIMAGEWRITERDOTC 1
#include "vars.h"
#endif


#ifdef XLIB


       /* These are used as arguments to nearly every Xlib routine, so it saves
        * routine arguments to declare them global.  If there were
        * additional source files, they would be declared extern there. */
Display *display;
int screen_num;
unsigned long rgb_white;
unsigned long rgb_black;
int bigwin=0;
int displaymemready=0;
int winheight, winwidth;

GC gc0;
GC gc1;

XImage *iw_display;
Visual iw_visual;

#endif


// this files defines uint8, int8, etc. uint's are unsigeds, ints are signed.  The
// number following them indicates the size uint8 are 8 bits wide, uint32 are 32 bits.

//include <types.h>

#include "machine.h"
// Load the fonts up...
#include "iwfonts.h"


#define IWEMULATED     1

#define IW_TEXTMODE    0
#define IW_TEXT_ESC    1
#define IW_TEXT_CTRLA  2
#define IW_TEXT_CTRLUL 3
#define IW_GRAPHMODE   99
#define IW_TEXT_0X1D   0x1d


#define IW_REPEAT100 254 /* repeat 100's place */
#define IW_REPEAT10  253 /* repeat 10's  place */
#define IW_REPEAT1   252 /* repeat 1's   place */



/*
   DIP Switches.
   see: http://alt-www.corvis.ru/html/tech/Printers/upm/printers/mapiw2.htm
   (if you can get a good connection to it.)

   Country Font Selection: (Can be software overridden)

   DIP SWITCH Bank One.

        bit (bit 1=2^0, bit 2 is 2^1, bit 3 is 2^2)
        1,2,3     Effect.         Software Setting for the same:
        000       American Font.    ESC Z,^G,^@
        110       British  Font.    ESC Z,^D,^@,ESC D,^C,^@
        001       German   Font.    ESC Z,^C,^@,ESC D,^D,^@
        011       French   Font.    ESC Z,^A,^@,ESC D,^F,^@
        101       Sweedish Font.    ESC Z,^B,^@,ESC D,^E,^@
        100       Italian  Font.    ESC Z,^F,^@,ESC D,^A,^@
        111       Spanish  Font.    ESC D,^G,^@
        010       American Font 2.  ESC Z,^E,^@,ESC D,^B,^@

        bit 4-    72 lines (on) 66 lines (off)
        bit 5-    If on, AND all data with 127 (strip 8th bit)

        bit 6,7
        00        Elite Proportional (upto 160dpi)
        01        Elite          12cpi
        10        Ultracondensed 17cpi
        11        Pica           10cpi

        bit-8     Auto Line Feed. 1=on (auto LF after CR)     , 0=off (requires LF char)

   DIP Switch Bank Two

        bits1,2
        00       9600 bps serial connection (we ignore the connection here.)
        01       1200 bps serial connection (we ignore the connection here.)
        10       2400 bps serial connection (we ignore the connection here.)
        11       300  bps serial connection (we ignore the connection here.)


        bit3 -   handshake:  0= Xon/Xoff, 1=Hardware handshake. (We ignore this too.)

        bit4-8   ignored.

 */



/*
typedef struct
{
	int8 dipsw1;                // Defaults for ImageWriter DIP switches.
	int8 dipsw2;


	uint8  mode;
	uint8  lastseq;               // last escape sequence.
	uint16 submode;               // submode used to track ESC sequences.
	uint16 submode1;              // submode used to track ESC sequences.
	uint16 submode2;              // submode used to track ESC sequences.
	uint16 submode3;              // submode used to track ESC sequences.
	uint16 submode4;              // submode used to track ESC sequences.

	int8  charwidth;             // this is set to 0 for condensed, 1 for normal, 2 for double wide.
	int8  bold;                  // 1 sets boldness.
	int8  headline;              // 1 sets (doublewide bold) headline mode.
	int8  underline;             // 1 sets underline.

	int8  bidirectional;         //
	int8  autoCRoff;             // 1 disables auto CR on linefeed.
	int8  autoLF;                // 1 sets an auto LF after a CR.
	int8  linefeedpitch;         // 24=6 lines per feed, 18=8 lines per feed. (144/18 or 144/24) default is 24.

	int8  linefeedreverse;       // 0 normal line feed down, 1 feed up

	int8  slashzero;             // 1 sets slashedzeros.
	int8  propspacing;           // Sets the number of pixels between proportional chars.
	int8  LFVTFFareCR;           // Do Line Feeds, Vertical Tabs, Form Feeds act as CR as well?
	int8  AutoLFonFull;          // AutoLF when buffer is full? (Not implemented here since we don't use any buffers at all...)
	int8  elitespacing;          // elite proportional font spacing.
	int16 repeatchar;            // how many times to print a character.  * set to 1 when done *
	int8  fontnumber;            // current font number.
	int8  countryfont;           // current font number.
	int16 leftmargin;            // measured in cpi based on current font. For proportional: if elite=10cpi, if pica=9cpi
	int16 tabs[32];              // tab positions.
	int8  currentform;           // current form number (0-4)
	int8  vtabs[5][96][6];       // upto 96 vertical tabs can be set on upto 5 pages. Each vtab contains one of 5 tabs (BCDEF)
	int8  currentformnumber;     // which of the 6 forms am I on?
                              // IW will jump up or down to the next vtab.

	int16 currentCPI;            // Current Character Per Inch setting (in pixels for tabs.)
	int16 currentVCPI;           // Vertical Character CPI
	int16 currentVCPIdiv;        // Vertical Character CPI divisor (depends on HDPI)

 // this is the user programable font buffer.  It's really 175 chars, controls are ignored, etc.  To make life
 // easier I set this to 255, it's a bit wasteful, yes, but saves checking code.

	int16 progfont[256][19];     // programable fonts (95-8*16 or 175-8*8) 175 chars max 16 lines each
	int16 progfntwidth[175];     // what's the width of each char?
	int16 proglastwidth;         // what was the last character width sent to us?


 // this changes as fonts are switch.  This is the actual font used to print.
	int16 livefont[256][19];     // live font (95-8*16 or 175-8*8) 175 chars max 16 lines each
	int16 livefntwidth[256];     // what's the width of each char?

	int8  progfnoffset;          // 0 print on last bottom wires, 1 print on top wires
	int8  fourteeninchpaper;     // zero if 11", non-zero: 14"

	int16 cursor;                // current X cursor position of the print head in pixels.
	int16 line;                  // current Y cursor pos in lines (depends on font and pitch)
	int16 linepixel;             // current Y pos in pixels



	uint8* page;                 // this holds the memory for a given page.
	uint32 pagesize;             // this holds the page size in bits.
	uint32 pagenum;              // this holds the page number in bits.


	uint8 outputps,outputpcl,    // What kind of output do we create?
	outputxlib, xlib_skip;

	uint8 landscape;            // print out landscape if printer supports it?

 // stuff needed by xlib routine...  XSetWMProperties
	char **argv;   int  argc;

	int  debug;

 // Command line options...
	uint32 iw_def_dpi, iw_max_hdpi, iw_max_wdpi;
	double iw_paper_w, iw_paper_h;
	uint32 iw_max_x, iw_max_y, iw_bitsperpixel, iw_bytes_per_line;

	float   scalex, scaley;          // Scaling factors for output
	uint32  outmaxx, outmaxy, outputdpi;// Maximum size of output page, output page DPI.
	char *xpage;


} ImageWriterType;
*/
ImageWriterType IW;


/* max is 160hx144v dots per inch.
 *
 * Normal: 80 dpi, condensed is 136 dpi (8" across)
 *
 * custom chars can be upto 16 dots wide.  width is defined for each char...
 * and is either proportional or fixed. a custom char can be assigned to any keyboard position
 * that normally prints something (not control chars...) including upper/lower case
 *
 * the dot striking wires in the type head are 1-9 (1 top, 9 at bottom).  When designign
 * a custom char, you can use either top 8 (1-8) or bottom 8 (2-9)... Normal alphabet uses
 * 1-7 for caps, and 3-7 for lowercase with 8.9 being reserved for descenders such as tails
 * of g,y,p,q.  Wire 9 is used for underlining too...  Normal base for chars is wire 7
 *
 * LSB is top (wire 1 or 2), MSB is bottom (wire 8 or 9)
 *
 * to load a new char: (7 dots wide) assigning to "&" char:
 *
 *  ESC-ESC | & G Control-@ H H  H H Control-@ Control-D  (sans spaces)
 *
 * G is width code, it indicates that the top 8 wires print the symbol and that it is 7 dots wide
 * (G is 7th letter of alphabet).   After you load the new char by means of the sequence above, you
 * can print this can anytime by sending:
 *
 * [ESC] ['] [&] [ESC] [$]  These 5 chars change the printer's type style to the custom font, print
 * the symbol assigned, and change back to the normal font.
 *
 *
 * Printing graphics:
 * each line can be upto 1280 dots long.
 *
 * Column oriented graphics:
 *
 * The IW can print horizontal lines with dots in any pattern, each vertical column upto 8 dots is defined
 * by a separate ascii char, so a single line may require upto 1280 chars for its definition.  After it prints
 * each line the printer is ready to receive a new line...
 *
 * Each control code defining one horizontal line of dot graphics starts with one of the following 6 char
 * prefixes:
 *
 * (hex) 1B 47 n n n n - prints line corresponding to nnnn bytes.
 *       1b 53 n n n n - same as above (identical)
 *       1b 67 n n n n - print line corresponding to teh following nnnx8 data bytes (pattern repeated 8x?)
 *
 * The nnnn's are 4 ordinary numeric keyboard chars (0-9) and specifies the number of data bytes upto 9999
 * that follow.  This 6 char prefix plus the data bytes themselves constitute the complete control code
 * which may thus run upto 10,005 chars.
 *
 * The nnn after ESC g consist of 3 keyboard numerals and specifies the number of data bytes divided by eight
 * (upto 999) that follow.  ESC-g's are somewhat faster than ESC-S/ESC-G's. but otherwise is the same...
 * i.e. ESC g 010 and ESC G 0080 are equivalent.    *** In these and other ESC sequences you can replace the
 * leading 0's with spaces!
 *
 * Each of the data bytes defines a vertical column of eight dots printed by the type head.  A dot is printed
 * for each bit set to 1 in the data byte.  Bit 7 causes the dot at the bottom of the column to be printed, bit 0
 * causes the top to be printed.  i.e.
 *
 *  bit value
 *  1 0 * 1 lsbit
 *  2 1 * 1
 *  4 2   0
 *  8 3 * 1
 * 16 4   0
 * 32 5   0
 * 64 6 * 1
 *128 7 * 1 msbit
 *
 * The columns print from left to right starting at the left margin of the page.
 *
 * Dot Spacing ***
 *
 * The vertical spacing of the striker wires in the type of head is 1/72 of an inch.  The horizontal character
 * pitch that produces 72 dpi is extended, or(huh?) 9 chars per inch.  So if you select a vertical line feed
 * pitch of 16/144 of an inch, the result is a uniform matrix of dot positions -- 72 per inch in each direction
 * with a total density of 5184 dpi.  The dot size is such that the horz/vert lines appear connected for this
 * matrix... to produce 9 chars per inch horizontally and a lf pitch of 16/144 use:
 *
 *  ESC n ESC T16
 *
 * Although you can select finer scale horizontal dot spacing, it takes longer to print...
 *
 * (need to document big huge ESC code table...)
 *
*/



// cause a segfault so I can invoke gdb
#define DOPANIC         {char c;  char *v=NULL; char *w=(void *)(-1); \
                         while ( 1)  {c=*v; c=*w; *w=c; *v=c;  }       }


#define IW_AUTO_CR_AT_END 1


#define DIW_DEF_DPI (72)    /* Default DPI of the PS interpreter! */
#define DIW_MAX_HDPI (144)   /* Our image's DPI                    */
#define DIW_MAX_WDPI (160)   /* Our image's DPI                    */
#define DIW_PAPER_W (8.5)
#define DIW_PAPER_H (11.0)  /* might need to also take care of 14" paper */
#define DIW_MAX_X (DIW_MAX_WDPI * DIW_PAPER_W)
#define DIW_MAX_Y (DIW_MAX_HDPI * DIW_PAPER_H)
#define DIW_BITS_PER_PIXEL (4)  /* this is for future expansion to say, color, or IW LQ emulation */
                              /* If you change this, you'll have to change the plot/pixel color  functions   */
#define DIW_BYTES_PER_HLINE (DIW_MAX_X/2)



// These used to be defines, but they're better off as variables.

#define IW_DEF_DPI         (IW->iw_def_dpi)
#define IW_MAX_HDPI        (IW->iw_max_hdpi)
#define IW_MAX_WDPI        (IW->iw_max_wdpi)
#define IW_PAPER_W         (IW->iw_paper_w)
#define IW_PAPER_H         (IW->iw_paper_h)
#define IW_MAX_X           (IW->iw_max_x)
#define IW_MAX_Y           (IW->iw_max_y)
#define IW_BITS_PER_PIXEL  (IW->iw_bitsperpixel)
#define IW_BYTES_PER_HLINE (IW->iw_bytes_per_line)


uint16 iw_get_ypix(ImageWriterType *IW,uint8 line)   // need to correct this for current spacing.
{
     if (IW==NULL) {ALERT_LOG(0,"IW is null"); exit(1); }
     if (IW->page==NULL) {ALERT_LOG(0,"IW page buffer is null"); DOPANIC; }


     if (IW->currentVCPIdiv==0) IW->currentVCPIdiv=2;
     return (IW->currentVCPI/IW->currentVCPIdiv)*line;}

uint8 iw_pixel_color(ImageWriterType *IW,uint16 x, uint16 y);
uint8 iw_pixel_iwcolor(ImageWriterType *IW,uint16 x, uint16 y);
void iw_plot_inc(ImageWriterType *IW, int16 x,  int16 y);
void iw_plot(ImageWriterType *IW, int16 x,  int16 y, uint8 color);

// int iw_spitout_ps(ImageWriterType *IW,FILE *out,uint8 landscape);



//     void iw_cr(ImageWriterType *IW) { IW->cursor=IW->leftmargin; if (IW->debug) printf("IW-CR\n");}
void iw_cr(ImageWriterType *IW)
{
       /*  iw_plot_inc(IW,IW->cursor,IW->linepixel);
         iw_plot_inc(IW,IW->cursor,IW->linepixel+1);
         iw_plot_inc(IW,IW->cursor,IW->linepixel+2);
         iw_plot_inc(IW,IW->cursor,IW->linepixel+3);
         iw_plot_inc(IW,IW->cursor,IW->linepixel+4);
         iw_plot_inc(IW,IW->cursor,IW->linepixel+5);
         iw_plot_inc(IW,IW->cursor,IW->linepixel+6);
         iw_plot_inc(IW,IW->cursor,IW->linepixel+5);
         iw_plot_inc(IW,IW->cursor,IW->linepixel+7);

         iw_plot_inc(IW,IW->cursor+1,IW->linepixel+2);
         iw_plot_inc(IW,IW->cursor+2,IW->linepixel+3);
         iw_plot_inc(IW,IW->cursor+3,IW->linepixel+4);
         iw_plot_inc(IW,IW->cursor+4,IW->linepixel+5);
         iw_plot_inc(IW,IW->cursor+4,IW->linepixel+6);
         iw_plot_inc(IW,IW->cursor+4,IW->linepixel+7);
         iw_plot_inc(IW,IW->cursor+4,IW->linepixel+8);  */

    if (IW==NULL) {ALERT_LOG(0,"IW is null"); exit(1); }
    if (IW->page==NULL) {ALERT_LOG(0,"IW page buffer is null"); DOPANIC; }


	if (IW->debug) printf("IW-CR lmargin:%d,ypixel:%d,yline:%d\n",IW->leftmargin,IW->linepixel,IW->line);
	IW->cursor=IW->leftmargin;
}



// protos
void iw_lf(ImageWriterType *IW);

#ifdef DEBUG
void thermometer(const char *s,int percent);
void twirly(void);
#endif

// for postscriot output
#ifdef POSTSCRIPT
#include "iwemu-ps.c"
#endif

#ifdef PCL
#include "iwemu-pcl.c"
#endif

#ifdef XLIB
#include "iwemu-xlib.c"
#endif


void iw_clear_page(ImageWriterType *IW)
{
    if (IW==NULL) {ALERT_LOG(0,"IW is null"); exit(1); }
    if (IW->page==NULL) {ALERT_LOG(0,"IW page buffer is null"); DOPANIC; }
    if (!IW->pagesize) {ALERT_LOG(0,"ImageWriter at %p has zero byte page allocated to it!",IW->page); DOPANIC;}

    memset(IW->page,0,IW->pagesize);
}


// Allocate memory for an image.
int8 iw_malloc(ImageWriterType *IW)
{

    if (IW==NULL) {ALERT_LOG(0,"IW is null"); exit(1); }

	IW->pagesize=(IW_MAX_X*IW_MAX_Y/2);
    if (!IW->pagesize) {ALERT_LOG(0,"Pagesize is zero"); DOPANIC;}
    if (IW->page!=NULL) {ALERT_LOG(0,"IW page buffer is NOT null");  return 0;}

    IW->page=(uint8 *) malloc(IW->pagesize);

    if (IW->page==NULL) {ALERT_LOG(0,"Could not allocate memory for page."); exit(323); }

    ALERT_LOG(0,"Allocated %d bytes for IW:%p page:%pd",IW->pagesize,IW,IW->page);

	iw_clear_page(IW);

	return 0;
}


// This sends a scaled version of pixel color back to the caller.
uint8 iw_pixel_color(ImageWriterType *IW, uint16 x, uint16 y)
{
	uint16 sx, sy;

    if (IW==NULL) {ALERT_LOG(0,"IW is null"); exit(1); }
    if (IW->page==NULL) {ALERT_LOG(0,"IW page buffer is null"); DOPANIC; }
    if (!IW->pagesize) {ALERT_LOG(0,"ImageWriter at %p has zero byte page allocated to it!",IW->page); DOPANIC;}


    if (!IW) {ALERT_LOG(0,"Null Imagewriter passed!"); EXIT(324); }

	if (IW->scalex==0.0)
	{
		IW->scalex=(float) (IW->outmaxx/(float)(IW_MAX_X));
		IW->scaley=(float) (IW->outmaxy/(float)(IW_MAX_Y));
	}

	sx=(uint16)(  (float)(x) * IW->scalex  );
	sy=(uint16)(  (float)(y) * IW->scaley  );

	return iw_pixel_iwcolor(IW,sx,sy);
}


// Used to check the color of a pixel by other software.
uint8 iw_pixel_iwcolor(ImageWriterType *IW,uint16 x, uint16 y)
{
    uint16 color; //xbit, yline;
	uint32 pixbyte;


    if (IW==NULL) {ALERT_LOG(0,"IW is null"); exit(1); }
    if (IW->page==NULL) {ALERT_LOG(0,"IW page buffer is null"); DOPANIC; }
    if (!IW->pagesize) {ALERT_LOG(0,"ImageWriter at %p has zero byte page allocated to it!",IW->page); DOPANIC;}



	if (!IW) return 255;

	if (x>=IW_MAX_X || y>=IW_MAX_Y) return 255;

//  yline  =(y * IW_MAX_X/2 );
//  pixbyte=(x / 2 )+ yline;
//  xbit   =(x & 1);

	pixbyte=(x+(y*IW_MAX_X))/2; // two pixels for each byte, so divide by two.

	if (x&1)
	{
		color=(IW->page[pixbyte] & 0x0f);
	}
	else
	{
		color=(IW->page[pixbyte] & 0xf0)>>4;
	}
	return color;
}



// 1360 horizontal max, by 2240 vert max at 14" pages, or 1760 at 11"
void iw_plot(ImageWriterType *IW, int16 x,  int16 y, uint8 color)
{
    //uint16 yline, xbit;
	uint32 pixbyte;

    if (IW==NULL) {ALERT_LOG(0,"IW is null"); exit(1); }
    if (IW->page==NULL) {ALERT_LOG(0,"IW page buffer is null"); DOPANIC; }
    if (!IW->pagesize) {ALERT_LOG(0,"ImageWriter at %p has zero byte page allocated to it!",IW->page); DOPANIC;}


    if (!IW) {ALERT_LOG(0,"Null Imagewriter passed!"); EXIT(324); return; }

	if (!IW) return;


    if ( ((uint16)(x)>=IW_MAX_X || (uint16)(y)>=IW_MAX_Y) || (x<0 || y<0  ))  {if (IW->debug) ALERT_LOG(0,"OUT OF RANGE PLOT %d,%d\n",x,y);
		return;}

//  yline  =(y * IW_MAX_X/2        );
//  pixbyte=(x / 2 )+ yline;
//  xbit   =(x & 1);

	pixbyte=(x+(y*IW_MAX_X))/2; // two pixels for each byte, so divide by two.

	if (x & 1)
	{
		IW->page[pixbyte]=(IW->page[pixbyte] & 0xf0) | (color & 0x0f);
	}
	else
	{
		IW->page[pixbyte]=(IW->page[pixbyte] & 0x0f) | ((color & 0x0f)<<4);
	}
	return;
}


/* This should be the most used function.  When called it increases the
   color level of a pixels. Since the IW prints bold by printing twice over the
   same pixel, this will do the trick.  For this emulator, we reserve
   0=white, 1=normal black, 2=bold black, 3=superbold black.
   not sure what we will do for IW2 color support later, but 12 colors will
   be left undefined.  Maybe we can get rid of the bolds and use iw_plot only. */

void iw_plot_inc(ImageWriterType *IW,int16 x, int16 y)
{
    uint16 color; //yline, color,xbit;
	uint32 pixbyte;

    if (IW==NULL) {ALERT_LOG(0,"IW is null"); exit(1); }
    if (IW->page==NULL) {ALERT_LOG(0,"IW page buffer is null"); DOPANIC; }
    if (!IW->pagesize) {ALERT_LOG(0,"ImageWriter at %p has zero byte page allocated to it!",IW->page); DOPANIC;}

    if (!IW) {ALERT_LOG(0,"Null Imagewriter passed!"); EXIT(324); return; }

	if (!IW) return;
    if (((uint16)(x)>=IW_MAX_X || (uint16)(y)>=IW_MAX_Y) || (x<0 || y<0)) {if (IW->debug) DEBUG_LOG(0,"OUT OF RANGE PLOTINC %d,%d\n",x,y);
		return; }

//  yline  =(y * IW_MAX_X/2        );
  //pixbyte=(x / 2 )+ yline;
  //xbit   =(x & 1);

	pixbyte=(x+(y*IW_MAX_X))/2; // two pixels for each byte, so divide by two.

	if (x & 1)
	{
		color=(IW->page[pixbyte] & 0x0f)+1; if ( color>3) color=3;
		IW->page[pixbyte]=(IW->page[pixbyte] & 0xf0) | color;
	}
	else
	{
		color=((IW->page[pixbyte] & 0xf0)>>4)+1; if ( color>3) color=3;
		IW->page[pixbyte]=(IW->page[pixbyte] & 0x0f) | (color<<4);
	}
	return;
}



/*-----------------3/12/99 9:40PM-------------------
 * This function prints a graphic character vertically down
 * on the page based on the current cursor position, it then
 * increments the cursor position.
 * --------------------------------------------------*/

void iw_printbar(ImageWriterType *IW,uint8 c,uint8 lower)
{
	uint16 x,y,i,j;

    if (IW==NULL) {ALERT_LOG(0,"IW is null"); exit(1); }
    if (IW->page==NULL) {ALERT_LOG(0,"IW page buffer is null"); DOPANIC; }
    if (!IW->pagesize) {ALERT_LOG(0,"ImageWriter at %p has zero byte page allocated to it!",IW->page); DOPANIC;}


    if (!IW) {ALERT_LOG(0,"Null Imagewriter passed!"); EXIT(324); return; }

    if (!IW) return;

	x=IW->cursor;
	y=IW->linepixel;

	if (x>=IW_MAX_X || y>=IW_MAX_Y) return;
	if (lower>1) return;

	for (i=0,j=1; i<8; i++, j=j<<1)  if (c & j) iw_plot_inc(IW,x,y+i+lower);

	IW->cursor++;

 // maybe this shouldn't be on... not sure.
#ifdef IW_AUTO_CR_AT_END
	if ((unsigned)IW->cursor>IW_MAX_X) {iw_cr(IW); iw_lf(IW);}
#else
	if ((unsigned)IW->cursor>IW_MAX_X) {IW->cursor=IW_MAX_X;}
#endif



}


#define IW_FONT_SIZE  (126-31)



// how many times can the IW's head go over a spot before we consider it maximum black (used for bolding text)
// think of it as gray levels from 0 (white) to IW_MAX_BLACK, but 1 isn't too light a gray.
#define IW_MAX_BLACK 16

#ifdef DEBUG
static int pagenumber=0;
#endif

void iw_formfeed(ImageWriterType *IW)
{
	uint16 i;
	uint32 bx;
    #ifdef DEBUG
      char filename[256];
      FILE *imgfile=NULL;

      pagenumber++;
    #endif

    if (IW==NULL) {ALERT_LOG(0,"IW is null"); exit(1); }
    if (IW->page==NULL) {ALERT_LOG(0,"IW page buffer is null"); DOPANIC; }
    if (!IW->pagesize) {ALERT_LOG(0,"ImageWriter at %p has zero byte page allocated to it!",IW->page); DOPANIC;}


    fflush(stdout); fflush(buglog);

    // Make sure there's something to print!
    for (i=0,bx=0; bx<IW->pagesize && i==0; bx++)  i|=IW->page[bx];

    #ifdef DEBUG
      ALERT_LOG(0,"Dumping IW binary page buffer iwimg-page-%d-%p-%dx%d.bin",pagenumber,IW->page,IW_MAX_X,IW_MAX_Y);
      snprintf(filename,256,"iwimg-page-%d-%p-%dx%d.bin",pagenumber,IW->page,IW_MAX_X,IW_MAX_Y);
      imgfile=fopen(filename,"w");
      if (imgfile) {fwrite(IW->page,IW->pagesize,1,imgfile); fclose(imgfile); imgfile=NULL;}

    if (i==0)  {ALERT_LOG(0,"Skipping output of blank page for page #%d",pagenumber); return ; }
    #endif

	IW->pagenum++;
    ALERT_LOG(0,"\nRendering output page %d: ps:%d pcl:%d xlib:%d",IW->pagenum,IW->outputps,IW->outputpcl,IW->outputxlib);



#ifdef POSTSCRIPT
    if (IW->outputps)    iw_spitout_ps(IW,NULL,0);
#endif

#ifdef PCL
    if (IW->outputpcl)   iw_spitout_pcl(IW,NULL,0);
#endif

#ifdef XLIB
    if (IW->outputxlib)  iw_spitout_xlib(IW,NULL,0);
#endif



	if (IW->LFVTFFareCR) iw_cr(IW);                    // we only set vertical position here, should we do a CR too

	IW->linepixel=0;
	IW->line=0;
	iw_clear_page(IW);

	return;
}


// Zap VTAB's
void iw_reset_vtabs(ImageWriterType *IW)
{
    int8 i,j; //,k;

    if (IW==NULL) {ALERT_LOG(0,"IW is null"); exit(1); }


	for (j=0; j<5; j++)
		for (i=0; i<96; i++)
		{
			IW->vtabs[j][i][0]=0;  IW->vtabs[j][i][1]=0;  IW->vtabs[j][i][2]=0;  IW->vtabs[j][i][3]=0;  IW->vtabs[j][i][4]=0;  IW->vtabs[j][i][5]=0;
			if ((i % 6)==5) IW->vtabs[j][i][0]=1;  // set B vtab by default every 6 lines.
			if (i==66 && !(IW->dipsw1 & 16)) IW->vtabs[j][i][5]=1;    // set bottom of page for 66 lines
			if (i==72 && (IW->dipsw1 & 16)) IW->vtabs[j][i][5]=1;    // set bottom of page for 72 lines
		}
}




void iw_lf(ImageWriterType *IW)
{
    if (IW==NULL) {ALERT_LOG(0,"IW is null"); exit(1); }
    if (IW->page==NULL) {ALERT_LOG(0,"IW page buffer is null"); DOPANIC; }
    if (!IW->pagesize) {ALERT_LOG(0,"ImageWriter at %p has zero byte page allocated to it!",IW->page); DOPANIC;}


    if (IW->currentVCPIdiv==0) IW->currentVCPIdiv=2;  // avoid divide by zeros


	if ( IW->linefeedreverse)             // reverse line feed?
	{
		if (IW->debug) printf("reverse LF!!!\n");
		if (IW->line==0  && !(IW->dipsw1 & 16)) {IW->line=66; IW->linepixel=iw_get_ypix(IW,IW->line); return;}
		else if (IW->line==0 && (IW->dipsw1 & 16))  {IW->line=77; IW->linepixel=iw_get_ypix(IW,IW->line); return;}
		else {
			IW->linepixel-=(IW->currentVCPI/IW->currentVCPIdiv);
			IW->line--;
		}
	}
	else                                  // normal line feeds.
	{
		if (IW->debug) printf("IW-LF %d,%d+%d\n",IW->leftmargin,IW->linepixel,IW->currentVCPI/IW->currentVCPIdiv);

        IW->linepixel+=(IW->currentVCPI/IW->currentVCPIdiv); // Was /2 since it's nn/144.

        IW->line++;

        if (IW->line>65 && !(IW->dipsw1 & 16)) {iw_formfeed(IW); if (IW->debug) DEBUG_LOG(0,"LF triggering FF since line>65\n");}
        if ( IW->line>71 && (IW->dipsw1 & 16)) {iw_formfeed(IW); if (IW->debug) DEBUG_LOG(0,"LF triggering FF since line>71\n");}
	}

}



void iw_set_vline_pos(ImageWriterType *IW,uint16 line)
{
    if (IW==NULL) {ALERT_LOG(0,"IW is null"); exit(1); }
    if (IW->page==NULL) {ALERT_LOG(0,"IW page buffer is null"); DOPANIC; }
    if (!IW->pagesize) {ALERT_LOG(0,"ImageWriter at %p has zero byte page allocated to it!",IW->page); DOPANIC;}


    IW->line=line;
	IW->linepixel=iw_get_ypix(IW,line);
}

// Print a character in the current font...

void iw_printchar(ImageWriterType *IW, uint8 c)
{
	uint16 i,j,k,l;

    if (IW==NULL) {ALERT_LOG(0,"IW is null"); exit(1); }
    if (IW->page==NULL) {ALERT_LOG(0,"IW page buffer is null"); DOPANIC; }
    if (!IW->pagesize) {ALERT_LOG(0,"ImageWriter at %p has zero byte page allocated to it!",IW->page); DOPANIC;}


    if (c<31) return; // ignore control chars -- if the main loop didn't process'em, we ignore'em.

	if (c=='0' && IW->slashzero) c=0; // if Slashed zero use alternate char that lives in zero.

    if (IW->debug) DEBUG_LOG(0,"Char width: %d\n",IW->charwidth);


	for ( i=0; i<IW->livefntwidth[c];i++)
	{

		j=IW->livefont[c][i];

		if (IW->underline) j=j|128;      // handle underlines.
		if (j>256) {j=j>>1; k=1;}         // low font chars (y,j,g,q,p, etc.)
		else k=0;

		if (!IW->charwidth) IW->charwidth=1;

		for (l=0; l<IW->charwidth; l++)
		{
			iw_printbar(IW,j,k);             // plain
			if (IW->bold || IW->headline) {IW->cursor--; iw_printbar(IW,j,k);}  // print over the same spot if bold or headline.

         // if headline, we print twice as wide.
			if (IW->headline)             {iw_printbar(IW,j,k); IW->cursor--; iw_printbar(IW,j,k);}
		}

	}

// handle spaces around proportional fonts.
	if (IW->fontnumber==7)
	{ for (l=0; l<=IW->elitespacing; l++) iw_printbar(IW,0,0); }
	else if (IW->propspacing)
	{ for (l=0; l<=IW->propspacing; l++) iw_printbar(IW,0,0); }
}


void iw_settopofform(ImageWriterType *IW)
{

    if (IW==NULL) {ALERT_LOG(0,"IW is null"); exit(1); }
    if (IW->page==NULL) {ALERT_LOG(0,"IW page buffer is null"); DOPANIC; }
    if (!IW->pagesize) {ALERT_LOG(0,"ImageWriter at %p has zero byte page allocated to it!",IW->page); DOPANIC;}


	IW->vtabs[IW->currentform][IW->line][5]=1; // ???
    if (IW->debug) DEBUG_LOG(0,"IW_SetTopOfForm - not fully implemented!\n");
}


void iw_initialize(ImageWriterType *IW)
{
    int16 i,j; //,k;

    if (IW==NULL) {ALERT_LOG(0,"IW is null"); exit(1); }


	iw_reset_vtabs(IW);

	IW->cursor=0;             // current X cursor position of the print head in pixels.
	IW->line=5;               // current Y cursor pos in lines (depends on font and pitch)
	IW->linepixel=40;         // current Y pos in pixels

	IW->mode=IW_TEXTMODE;
	IW->lastseq=0;
	IW->submode1=0;
	IW->submode2=0;
	IW->submode3=0;


	IW->charwidth=1;             // this is set to 0 for condensed, 1 for normal, 2 for double wide.
	IW->bold=0;                  // 1 sets boldness.
	IW->headline=0;              // 1 sets (doublewide bold) headline mode.
	IW->underline=0;             // 1 sets underline.
	IW->bidirectional=0;         //
	IW->pagenum=0;
	IW->autoCRoff=0;             // 1 disables auto CR on linefeed.
 // IW->autoLF=??;               // 1 sets an auto LF after a CR.

//  IW->linefeedpitch=??;        // 24=6 lines per feed, 18=8 lines per feed. (144/18 or 144/24) default is 24.
	IW->linefeedreverse=0;       // 0 normal line feed down, 1 feed up

 // IW->slashzero=??;            // 1 sets slashedzeros.

	IW->propspacing=0;           // Sets the number of pixels between proportional chars.  0=non prop font.
	IW->LFVTFFareCR=0;           // Do Line Feeds, Vertical Tabs, Form Feeds act as CR as well?
	IW->AutoLFonFull=0;          // AutoLF when buffer is full? (Not implemented here.)
	IW->elitespacing=2  ;        // elite proportional font spacing.
	IW->repeatchar=1;            // how many times to print a character.  * set to 1 when done *
	IW->fontnumber=IW->dipsw1 & 7; // current font number copy from dipswitch
	IW->leftmargin=5;            // measured in cpi based on current font. For proportional: if elite=10cpi, if pica=9cpi

//  for ( i=0; i<32; i++) { IW->tabs[i]=0; } ????

	IW->currentform=0;            // current form number (0-4)
	IW->currentCPI=16;            // Current Character Per Inch setting (in pixels for tabs.)

                               // Vertical Character CPI (divide by two to get pixels for ESC T nn and Dipswitch1,)
	IW->currentVCPI=18;           // ((IW->dipsw1 & 16) ? 18: 16);
	IW->fourteeninchpaper=(IW->dipsw1 & 16);


 // have to load the default font here!



	if ( (IW->fontnumber==3 || IW->fontnumber==7) || IW->propspacing) // proportional?
	{
		for (i=0; i<128; i++)
		{ IW->livefntwidth[i]=iwpropw[IW->fontnumber][i];
			for (j=0; j<19; j++) IW->livefont[i][j]=iwprop[IW->fontnumber][i][j];
		}
	}
	else
	{
		for (i=0; i<128; i++)
		{ IW->livefntwidth[i]=8;
			for (j=0; j<8; j++) {IW->livefont[i][j]=iwfixed[IW->fontnumber][i][j];}
		}

	}

    iw_malloc(IW);

}

#ifdef DEBUG
void twirly(void)
{
	static int8 loc; static char *cursor="-/|\\";
	loc++; loc=0x03;
    DEBUG_LOG(0,"\r%c  \r",cursor[loc]);
}

void thermometer(const char *s,int percent)
{
	char buf[44];
	strncpy(buf,"####################",21);
	if (percent>100) percent=100;
	strncpy(buf+(percent/5),":::::::::::::::::::",19); buf[20]=0;
    DEBUG_LOG(0,"\r  %20s:  %3d%% %10s    \r",s,percent,buf);
}
#endif

/**********************************************************************************\
* Printer State Machine.                                                           *
*                                                                                  *
* This interprets various IW commands and functions, switches between different    *
* modes of the printer.                                                            *
*                                                                                  *
*                                                                                  *
\**********************************************************************************/

void ImageWriterLoop(ImageWriterType *IW, uint8 c)
{

    #ifdef DEBUG
     char filename[256];
     FILE *iwdebug;
    #endif




	char c2;
	int16 page=0, line=0,i,j;

    //ALERT_LOG(0,"ImageWriter:%p scc_a:%p scc_b:%p IW->page:%p IW->pagesize:%d",IW,scc_a_IW,scc_b_IW,IW->page,IW->pagesize);


    if (IW==NULL) {ALERT_LOG(0,"IW is null"); exit(1); }
    if (IW->page==NULL) {ALERT_LOG(0,"IW page buffer is null"); DOPANIC; }
    if (!IW->pagesize) {ALERT_LOG(0,"ImageWriter at %p has zero byte page allocated to it!",IW->page); DOPANIC;}


    #ifdef DEBUG
     snprintf(filename,256,"imagewriter-output-%p.iw",IW);
     iwdebug=fopen(filename,"a+");
     if (iwdebug) {fwrite((void *)(&c),1,1,iwdebug); fflush(iwdebug); fclose(iwdebug); iwdebug=NULL;}
    #endif

    IW->debug=0;

    //if (IW->debug) DEBUG_LOG(0,"\nloop: 0x%2x mode:%d ",c,IW->mode);

	if (IW->dipsw1 & 32) {c=c & 0x7f; // are we filtering the high bit?
        if (IW->debug) DEBUG_LOG(0,"filtering high bit!\n");
	}


	switch (IW->mode)
	{
		case IW_TEXT_ESC: // Escape Mode Text.

			if (IW->debug) printf("in ESCmode c=%c,0x%x LastSeq: %c 0x%2x submodes:%d,%d,%d,%d\n\n",(c>' ' && c<126 ? c : '?'  ),c,IW->lastseq,IW->lastseq, IW->submode1, IW->submode2, IW->submode3, IW->submode4);

			if (IW->lastseq) // are we already in the process of handling a long escape code?  If so resume it.
			{
				switch(IW->lastseq)
				{

					case 'L': // Set Left Margin.  // here I use c & 15 to get numbers since 0 may be replaced by a space. 32 & 15=0 '0' & 15=0.
                        if (IW->debug) DEBUG_LOG(0,"ESC L - Set Left Margin %d\n",IW->leftmargin);
						if (IW->submode1==0) {IW->leftmargin=(c & 15)*100; IW->submode1=1; return;}
						if (IW->submode1==1) {IW->leftmargin+=(c & 15)*10; IW->submode1=2; return;}
						if (IW->submode1==2) {IW->leftmargin+=(c & 15);                    return;}
						IW->mode=IW_TEXTMODE; return;

					case 'F' : // fine position the print head at nnnn from left margin.

						if (IW->submode1<4)
						{
							IW->submode1++; if (c==' ') c='0';
							if (c<'0' || c>'9') {IW->mode=IW_TEXTMODE; return;}
							IW->submode2=(IW->submode2*10)+(c-'0');
							if (IW->submode1<4) return; // return on n's 0,1,2 only, on 3rd fall through.
						}
                        if (IW->debug) DEBUG_LOG(0,"ESC F %04d\n",IW->submode2);

						IW->cursor=(IW->leftmargin + IW->submode2);
						IW->mode=IW_TEXTMODE;
						return;


					case 'T' :                      // Set Line spacing.
                                        // 16/144
						if (c==' ') c='0';
						if (c<'0' || c>'9')  {IW->mode=IW_TEXTMODE; return;}
						if (IW->submode1==0) {IW->submode2=c-'0'; IW->submode1++; return;}
						if (IW->submode1==1)
						{
							IW->submode2=(c-'0')+(IW->submode2*10);
							IW->currentVCPI=IW->submode2;       // Vertical Character CPI
							if (IW->debug) printf("ESC T:%d \n",IW->currentVCPI);
						}
						IW->mode=IW_TEXTMODE; return;

					case 'V' :   // print a repeating graphics upto nnnn bars of the same pattern for lines

						if (IW->submode1<4)
						{
							IW->submode1++; if (c==' ') c='0';
							if (c<'0' || c>'9') {IW->mode=IW_TEXTMODE; return;}
							IW->submode2=(IW->submode2*10)+(c-'0');
							if (IW->submode1<4) return; // return on n's 0,1,2 on 3rd one fall through.
						}

						if (IW->submode2) for (i=0; i<IW->submode2; i++) iw_printbar(IW,c,0);
                        if (IW->debug) DEBUG_LOG(0,"ESC V - Repeating graphic bar %x times %d\n",c,IW->submode);

						IW->mode=IW_TEXTMODE;
						return;



					case 'G' :   // print raw graphics
						if (IW->submode1<4)
						{
							IW->submode1++; if (c==' ') c='0';
							if (c<'0' || c>'9') {if (IW->debug) printf("Exiting Graphics mode due to bad char: sub:%d,char %2x, nnn:%d\n",IW->submode1, c, IW->submode2);
								IW->mode=IW_TEXTMODE; return;}
							IW->submode2=(IW->submode2*10)+(c-'0');
							return;
						}

						if (IW->submode2)
						{
							iw_printbar(IW,c,0); IW->submode2--;
                            if (IW->debug) DEBUG_LOG(0,"Graphics Mode: cursor(%d,%d:%d)\n",IW->cursor,IW->linepixel,IW->line);
							if (!IW->submode2) {if (IW->debug) printf("Normal graphics exit\n");	IW->mode=IW_TEXTMODE; // if we run out of glyphs, bail back to text mode.
							}

						}
						else {IW->mode=IW_TEXTMODE; if (IW->debug) printf("Normal graphics exit\n");}

						return;


					case 'g' :   // print graphics
						if (IW->submode1<3)
						{
							IW->submode1++; if (c==' ') c='0';
							if (c<'0' || c>'9') {IW->mode=IW_TEXTMODE; return;}
							IW->submode2=(IW->submode2*10)+(c-'0');
							if (IW->submode1<3)  return; // return on n's 0,1,2, on 3 fall through
						}
						IW->submode2=IW->submode2<<3;  // multiply by 8 for this mode.

                        if (IW->debug) DEBUG_LOG(0,"ESC g - Graphics *8  %d submode2:%d\n",c,IW->submode2);
						IW->lastseq='G'; IW->submode1=4; return;  // continue in 'G' mode.



					case 115: // proportional text mode spacing between chars.  (ESC s)
                        if (IW->debug) DEBUG_LOG(0,"ESC s  - Proportional Text:%x  \n",c);
						if (c==' ') c='0';
						if (c<'0' || c>'9') return;
						IW->propspacing=(c - '0');
                        if (IW->debug) DEBUG_LOG(0,"Valid ESC s  - Proportional Text:%x  \n",c);

						IW->mode=IW_TEXTMODE;
						return;

					case 'I':    // about to load new character set.
                            // first character sent picks ascii of char to replace.

                        if (IW->debug) DEBUG_LOG(0,"ESC I  - Load new font (current:%x) char to change:%x Width:%d \n",c,IW->submode1,IW->submode2);

						if (IW->submode1==0) IW->submode1=c; return;  // submode 1 is which char.
						if (IW->submode2==0)  // next the width of this particular character
						{
							if (c>='a' && c<='p')       // bottom
							{IW->submode2=c-'a'; IW->progfntwidth[IW->submode1]=c-'a'; IW->submode2=1+(IW->progfnoffset=0); return;}
							else if (c>='A' && c<='P')  // top
							{IW->submode2=c-'A'; IW->progfntwidth[IW->submode1]=c-'A'; IW->submode2=1+(IW->progfnoffset=1); return;}
							else {IW->mode=IW_TEXTMODE; return;}
						}
                             // at this point we got ESC I,char,its width.
                             // bit 0 is top wire, bit 7 is bottom.

                             // bail out if we already got our bits and a control D.
						if (c==0x04 && (IW->submode3==IW->progfntwidth[IW->submode1])) {IW->mode=IW_TEXTMODE; return;}
						else if (IW->submode3==IW->progfntwidth[IW->submode1])
						{
                                      // If not ^D, we're expecting more, so set the char to change to C
                                      // and switch modes back.
							IW->submode1=c; IW->submode2=0; IW->submode3=0; return;
						}

                             //           char          line

						IW->progfont[IW->submode1][IW->submode3++]=c;
						if (IW->submode3==IW->progfntwidth[IW->submode1]) {IW->submode1=c; IW->submode2=0; IW->submode3=0;}
						return;


					case IW_REPEAT100: // repeat 100's place.
                        if (IW->debug) DEBUG_LOG(0,"Repeat a character 100 place. %x \n",c);
						if (c==' ') c=0;
						if (c<'0' || c>'9') {IW->mode=IW_TEXTMODE;return;}
						IW->repeatchar=0;
						IW->repeatchar+=(c-'0') * 100;
						IW->lastseq=IW_REPEAT10;
						return;

					case IW_REPEAT10: // repeat 100's place.
                        if (IW->debug) DEBUG_LOG(0,"Repeat a character 10 place. %x \n",c);
						if (c==' ') c=0;
						if (c<'0' || c>'9') {IW->mode=IW_TEXTMODE;return;}
						IW->repeatchar+=(c-'0') * 10;
						IW->lastseq=IW_REPEAT1;
						return;

					case IW_REPEAT1: // repeat 1's place.
                        if (IW->debug) DEBUG_LOG(0,"Repeat a character 1 place. %x \n",c);
						if (c==' ') c=0;
						if (c<'0' || c>'9') {IW->mode=IW_TEXTMODE;return;}
						IW->repeatchar+=(c-'0');
						IW->lastseq=0;
						return;
					case 'Z':       // ESC Z mode.
                        if (IW->debug) DEBUG_LOG(0,"ESC Z mode 8 bit mode if null space, @NUL sets LF to be CR %x \n",c);
						if (IW->submode1==0)  // ESC Z Control-A
						{
							if (c==0) IW->submode1=1280; // ESC Z NULL SPACE sets 8 bit on or off!
							if (c==1) IW->submode1=1;
							if (c==64) IW->submode1=64; // ESCZ@NUL sets LF,VT,FF to be recognized as CR
							if (c==' ') IW->submode1=' '; // ESCZ space NUL sets no LineFeed when buffer full (ignored in emulator.)
							return;
						}

						if (IW->submode1==1)  // ESC Z Control-A,Control@
							if (c==0)
							{
                                if (IW->debug) DEBUG_LOG(0,"ESC Z ^A ^@ - End Slashed Zero  %x \n",c);
								IW->submode1=0; IW->lastseq=0;
								IW->slashzero=0;
								IW->mode=IW_TEXTMODE;
								return;
							}

						if (IW->submode1==64)  // ESC Z @ NUL
							if (c==0)
							{IW->submode1=0; IW->lastseq=0;
								IW->LFVTFFareCR=0;
								IW->mode=IW_TEXTMODE;
                                if (IW->debug) DEBUG_LOG(0,"ESC Z @ NUL - LF,VT,FF-> CR  %x \n",c);
								return;
							}
						if (IW->submode1==1280)  // ESC Z  NUL 32
							if (c==32)
							{IW->submode1=0; IW->lastseq=0;
								IW->dipsw1=IW->dipsw1 & (255-32); // disable SW1-5 allowing 8 bit data.
								IW->mode=IW_TEXTMODE;
                                if (IW->debug) DEBUG_LOG(0,"ESC Z NUL 32 - Allow 8 bit data %x \n",c);
								return;
							}
						if (IW->submode1==' ')  // ESC Z _ NUL
							if (c==0)
							{IW->submode1=0; IW->lastseq=0;
								IW->AutoLFonFull=0;
								IW->mode=IW_TEXTMODE;
                                if (IW->debug) DEBUG_LOG(0,"ESC Z _ NUL - Disable Auto LF on buffer full %x \n",c);
								return;
							}


                        if (IW->debug) DEBUG_LOG(0,"ESC Z - Disable Auto LF after each CR. %x \n",c);

						if (IW->submode1==128) // Disable Auto LF after each CR?
							if (c==1) {IW->autoLF=0; IW->lastseq=0; IW->mode=IW_TEXTMODE; return;}
						if (c==128) {IW->submode1=128; return;}

						IW->mode=IW_TEXTMODE;
						return;

					case 'D':       // ESC D mode.
						if (IW->submode1==0)  // ESC D Control-A
						{
							if (c==0) IW->submode1=1280; // ESC Z NULL SPACE sets 8 bit on or off!
							if (c==1) IW->submode1=1;
							if (c==64) IW->submode1=64;
							if (c==' ') IW->submode1=' '; // ESCZ space NUL sets no LineFeed when buffer full (ignored in emulator.)
							return;
						}

						if (IW->submode1==1)  // ESC D Control-A,Control@
							if (c==0)
							{IW->submode1=0; IW->lastseq=0;
								IW->slashzero=1;
								IW->mode=IW_TEXTMODE;
                                if (IW->debug) DEBUG_LOG(0,"ESC D ^A ^@ Slashed Zero on   %x \n",c);
								return;
							}

						if (IW->submode1==64)  // ESC Z @ NUL
							if (c==0)
							{IW->submode1=0; IW->lastseq=0;
								IW->LFVTFFareCR=1;
								IW->mode=IW_TEXTMODE;
                                if (IW->debug) DEBUG_LOG(0,"ESC D @ NUL - LF,VT,FF ->CR on %x  \n",c);
								return;
							}


						if (IW->submode1==' ')  // ESC Z space NUL
							if (c==0)
							{IW->submode1=0; IW->lastseq=0;
								IW->AutoLFonFull=1;
								IW->mode=IW_TEXTMODE;
                                if (IW->debug) DEBUG_LOG(0,"ESC D 32 NUL - AutoLF on buffer full on  %x  \n",c);
								return;
							}

						if (IW->submode1==1280)  // ESC Z  NUL 32
							if (c==32)
							{IW->submode1=0; IW->lastseq=0;
								IW->dipsw1 |=32; // enable SW1-5 filtering 8 bit data.
								IW->mode=IW_TEXTMODE;
                                if (IW->debug) DEBUG_LOG(0,"ESC D NUL 32 - Ignore 8th bit on data!   %x  \n",c);
								return;
							}
                                //     if (IW->submode1==' ')  // ESC Z _ NUL
                        if (IW->debug) DEBUG_LOG(0,"ESC D _ NUL Auto LF after CR?            %x  \n",c);

						if (IW->submode1==128) // Auto LF after each CR?
							if (c==1) {IW->autoLF=1; IW->lastseq=0; IW->mode=IW_TEXTMODE; return;}
						if (c==128) {IW->submode1=128; return;}

						IW->mode=IW_TEXTMODE;
						return;

					case 0x6c: // Disable autoCR after LF // ESC l

                        if (IW->debug) DEBUG_LOG(0,"ESC l CR before LF?= %x  \n",c);
						if (c=='1') {IW->autoCRoff=0; IW->lastseq=0; return;}
						if (c=='0') {IW->autoCRoff=1; IW->lastseq=0; return;}

/*                           case 0x54: // set line feed pitch.
                                      if (IW->submode1==0) {IW->submode1=1; IW->submode2=((c % 10) *10); return;}
                                      if (IW->submode1==1) {IW->submode1=0; IW->linefeedpitch=IW->submode2+(c % 10); return;}
*/

					case '(':  // set horizontal tabs.
                        if (IW->debug) DEBUG_LOG(0,"ESC ( Set HTABS...   %x  \n",c);
						if (c=='.') { IW->mode=IW_TEXTMODE; return;}
						if ( (c>='0' && c<='9') || c==' ')
						{ if (c==' ') c='0';
							IW->submode2=(c-'0'+(IW->submode2*10)) & 255;
							IW->tabs[IW->submode1]=IW->submode2 * IW->currentCPI;
							return;
						}
						if (c==',') {IW->submode1++; IW->submode2=0; IW->submode1 &=0x1f; return;}
						IW->mode=IW_TEXTMODE; return;

					case ')': // clear an individual horizontal tab
                        if (IW->debug) DEBUG_LOG(0,"ESC ( Clea an HTABS...   %x  \n",c);
						if (c==' ') c='0';
						if (c>='0' && c<='9') IW->submode2=c-'0' + (10*IW->submode2);
						IW->submode1++;
						if (IW->submode1>=3)
						{ for (i=0; i<32; i++) if (IW->tabs[i]==IW->submode2) IW->tabs[i]=0; IW->mode=IW_TEXTMODE;}

						return;


					default:      IW->mode=IW_TEXTMODE;
                        if (IW->debug) DEBUG_LOG(0,"** BAD ESC Sequence!!!  %x  \n",c);
						return;

				}
			}
			IW->lastseq=0;
			IW->submode1=0;
			IW->submode2=0;
			IW->submode3=0;

			switch(c)
			{

         // Monospace font sizes:
				case 'n': IW->fontnumber=0; IW->mode=IW_TEXTMODE;return;            // 9 cpi    72dpi  576dots per line extended
				case 'N': IW->fontnumber=1; IW->mode=IW_TEXTMODE;return;            // 10cpi    80dp   640dots per line pica
				case 'E': IW->fontnumber=2; IW->mode=IW_TEXTMODE;return;            // 12cpi    96dp   768dots per line elite  *** Elite ***

				case 'p': IW->fontnumber=3; IW->propspacing=1; IW->mode=IW_TEXTMODE; return;            // Pica Prop       144dpi 1152dots per line elite proportional.
				case 'P': IW->fontnumber=7; IW->propspacing=1; IW->mode=IW_TEXTMODE; return;            // Elite Prop      144dpi 1152dots per line elite proportional.

				case 'e': IW->fontnumber=4; IW->mode=IW_TEXTMODE;return;            // 13.4cpi 107dpi  856dots per line semicondensed.
				case 'q': IW->fontnumber=5; IW->mode=IW_TEXTMODE;return;            // 15cpi   120dpi  960dots per line Condensed.
				case 'Q': IW->fontnumber=6; IW->mode=IW_TEXTMODE;return;            // 17cpi   136dpi 1088dots per line UltraCondensed.

				case 115: // proportional text mode.  Next char is size of dots between chars.
					IW->lastseq=115;
					return;
         // proportional spacing for selected chars in elite font only.
				case '1': if (IW->fontnumber==3) IW->elitespacing=1;    IW->mode=IW_TEXTMODE; return;
				case '2': if (IW->fontnumber==3) IW->elitespacing=2;    IW->mode=IW_TEXTMODE; return;
				case '3': if (IW->fontnumber==3) IW->elitespacing=3;    IW->mode=IW_TEXTMODE; return;
				case '4': if (IW->fontnumber==3) IW->elitespacing=4;    IW->mode=IW_TEXTMODE; return;
				case '5': if (IW->fontnumber==3) IW->elitespacing=5;    IW->mode=IW_TEXTMODE; return;
				case '6': if (IW->fontnumber==3) IW->elitespacing=6;    IW->mode=IW_TEXTMODE; return;
				case '7': if (IW->fontnumber==3) IW->elitespacing=7;    IW->mode=IW_TEXTMODE; return;
				case '8': if (IW->fontnumber==3) IW->elitespacing=8;    IW->mode=IW_TEXTMODE; return;


         // direct graphics printing.

				case 'G' :                     // both ESC G and ESC S are identical in function.
                case 'S' : if (IW->debug) DEBUG_LOG(0,"ESC S = ESC G Switching lastseq to G\n");
					IW->lastseq='G'; return;

				case 'g' : IW->lastseq='g'; return;  // print graphics corresponding to a pattern.



				case 'V' : IW->lastseq='V'; return;  // repeating line of graphics upto nnnn bits.

				case 'F' : IW->lastseq='F'; return;  // fine position printhead at nnnn offset from left margin.


         // programable fonts

				case '+' : IW->proglastwidth=8; IW->mode=IW_TEXTMODE; return;

				case '-' : IW->proglastwidth=16; IW->mode=IW_TEXTMODE; return;

				case 'I' : IW->lastseq='I'; return;  // load fonts


         // custom or normal font selection.

				case '\'':                     // switch to custom font

					memcpy(IW->livefont,IW->progfont,(128*16*sizeof(int16)));
					memcpy(IW->livefntwidth,IW->progfntwidth,(sizeof(int8)*128));
					IW->mode=IW_TEXTMODE; return;
				case '*' :                     // switch to custom font high bit chars.

					memcpy(IW->livefont,&IW->progfont[128],(128*16*sizeof(int16)));
					memcpy(IW->livefntwidth,&IW->progfntwidth[128],(sizeof(int8)*128));
					IW->mode=IW_TEXTMODE; return;

				case '$' :                     // switch to normal font.

					if ( (IW->fontnumber==3 || IW->fontnumber==7) || IW->propspacing)             // which font? Proportional or fixed?
					{
						for (i=0; i<128; i++)
						{ IW->livefntwidth[i]=iwpropw[IW->fontnumber][i];
							for (j=0; j<18; j++) IW->livefont[i][j]=iwprop[IW->fontnumber][i][j];
						}
					}
					else
					{
						for (i=0; i<128; i++)
						{ IW->livefntwidth[i]=8;
							for (j=0; j<18; j++) IW->livefont[i][j]=iwfixed[IW->fontnumber][i][j];
						}

					}
					IW->mode=IW_TEXTMODE; return;



         // Left Margin. ESC L, nnn
				case 'L': IW->lastseq='L'; return;

         // repeated character.
				case 'R': IW->lastseq=IW_REPEAT100; return;

         // to slash or not to slash zeros, that is the question.
				case 'Z': IW->lastseq='Z'; return;
				case 'D': IW->lastseq='D'; return;


         // To underline or not to underline?
				case 'X': IW->underline=1; IW->lastseq=0; IW->mode=IW_TEXTMODE; return;
				case 'Y': IW->underline=0; IW->lastseq=0; IW->mode=IW_TEXTMODE; return;


         // To bold or not to bold?
				case '!': IW->bold=1; IW->lastseq=0; IW->mode=IW_TEXTMODE; return;
				case '"': IW->bold=0; IW->lastseq=0; IW->mode=IW_TEXTMODE; return;


         // To bidir or not
				case '<': IW->bidirectional=1; IW->lastseq=0; IW->mode=IW_TEXTMODE; return;
				case '>': IW->bidirectional=0; IW->lastseq=0; IW->mode=IW_TEXTMODE; return;


				case 0x6c: IW->lastseq=0x6c; return;
         //case 0x54: IW->lastseq=0x54; return;


         // Line Feed Pitch.
				case 'A': IW->linefeedpitch=24; IW->currentVCPI=18; IW->lastseq=0; IW->mode=IW_TEXTMODE; return;
				case 'B': IW->linefeedpitch=18; IW->currentVCPI=16; IW->lastseq=0; IW->mode=IW_TEXTMODE; return;


         // Forward or Reverse Line Feeds.
                case 'r': {IW->linefeedreverse=1; IW->mode=IW_TEXTMODE;  if (IW->debug) DEBUG_LOG(0,"!! Reverse Line Feed used !!\n");
						return;}
                case 'f': {IW->linefeedreverse=0; IW->mode=IW_TEXTMODE;  if (IW->debug) DEBUG_LOG(0,"Forward LF selected.!!\n");
						return;}

         // ESC v is Set Top of Form.  we can likely ignore this.
				case 'v': iw_settopofform(IW);  // might need to implement this -- or not.
					IW->mode=IW_TEXTMODE; return;

         // Set line spacing usually 16.
				case 'T': IW->lastseq='T'; return;

         // Paper Detector Error light.  We can ignore this totally.  These codes enable
         // or disable the paper error light on the IW console.  They don't return shit to the Lisa.
     // Since we don't care about the light on the console, these are ignored.
				case 'o': IW->mode=IW_TEXTMODE; return;
				case 'O': IW->mode=IW_TEXTMODE; return;

                case 'c': if (IW->debug) DEBUG_LOG(0,"Reinitialize Printer to Soft defaults ESC c\n");
					iw_formfeed(IW); iw_initialize(IW);
					IW->mode=IW_TEXTMODE;
					return;

     // Set Horizontal tabs.  ESC ( nnn,nnn,nnn. Leading n's can be 0's or spaces. End with a dot.
				case '(': IW->lastseq='('; IW->submode1=0; IW->submode2=0; IW->submode3=0; return;


				case 'u': // set the current position as a tab stop.
					if (IW->cursor)
					{
						for (i=0; i<32; i++)
							if (IW->tabs[i]==0) {IW->tabs[i]=IW->cursor; i=32;}
					}
					IW->mode=IW_TEXTMODE; return;


				case '0': // clear all tabs
					for (i=0; i<32; i++) IW->tabs[i]=0;
					IW->mode=IW_TEXTMODE; return;

				case ')': // clear a specific tab
					IW->lastseq=')'; IW->submode1=0; IW->submode2=0; IW->submode3=0; return;



                default: if (IW->debug) DEBUG_LOG(0,"*** UNKNOWN ESC SEQUENCE %c %x %d\n",c,c,c);

					IW->mode=IW_TEXTMODE; return;  // ignore unknown esc sequences.
			}

		case IW_TEXT_CTRLA: // so far this is only to set slashed zeros or not.  Might need to expand this, this is ignored now.

			if (c==0) {IW->mode=IW_TEXTMODE; return;  }

			IW->mode=IW_TEXTMODE; return;



		case IW_TEXTMODE:
			switch (c)
			{
				case 27: // escape character.
					IW->lastseq=0; IW->submode1=0; IW->submode2=0; IW->submode3=0;
					IW->mode=IW_TEXT_ESC;
					return;

				case 1:  // control-A;          // also used to go to next top of page or bottom of page vtab???
					IW->mode=IW_TEXT_CTRLA;
					return;


				case 0x1f :                     // control_ (control under line)
					IW->mode=IW_TEXT_CTRLUL; return;


				case 12 :    // control L -- jump to next page (page feed.)
                    if (IW->debug) DEBUG_LOG(0,"FF/Next Form requested via ^L\n");
					page=IW->currentformnumber; IW->currentformnumber=((page+1) % 5);

					for (i=0; i<96; i++) if (IW->vtabs[page][i][5]) {iw_set_vline_pos(IW,i); return;}

                     // incase we didn't find the next form, spit out the whole page.
					iw_formfeed(IW); return;


				case 0x1d: // 0x1d mode - used to set top of form
					IW->mode=IW_TEXT_0X1D;     IW->submode=0; IW->submode1=0; IW->submode2=0;
					return;


				case 10: // line feed
                    if (IW->debug) DEBUG_LOG(0,"Got LF from IW, AutoCRoff:%d, LFVTFFareCR:%d AutoCR Condition %d\n",IW->autoCRoff,IW->LFVTFFareCR,((!IW->autoCRoff || IW->LFVTFFareCR) ));
					iw_lf(IW);
					if (!IW->autoCRoff || IW->LFVTFFareCR) iw_cr(IW);
					return;

				case 9     : // tab ^I=TAB  horizontal tab
                    // Find nearest tab to the right of the print head.
					j=0;
					for (i=0; i<32; i++) if (IW->tabs[i]>IW->cursor) if (IW->tabs[i]<j) j=IW->tabs[i];
                    // jump to that if its found.

                    if (IW->debug) DEBUG_LOG(0,"^I (Tab) from %d to %d (ignore if 0)\n",IW->cursor,j);

					if (j) IW->cursor=j;
					return;

    /*    case 12: // form feed. OLD CODE... Handled above a better way...
                   if (IW->LFVTFFareCR) // If LFVTFFareCR mode feed a CR first.
                   {
                    if (!IW->autoLF) iw_lf(IW);
                    iw_cr(IW);
                   }
    */
				case 13: // carriage return
                    if (IW->debug) DEBUG_LOG(0,"Got CR from IW, AutoLF is %d\n",IW->autoLF);
					if (IW->autoLF) iw_lf(IW);
					iw_cr(IW);
					return;


        /* case 31: // multiple line feeds.  Gonna treat this like a fake escape code.
                 IW->mode=IW_TEXT_ESC;
                 IW->lastseq=27;
                 return;
        */




         // To headline or not?
				case 14      : IW->headline=1; IW->lastseq=0; IW->mode=IW_TEXTMODE; return; // ^N
				case 15      : IW->headline=0; IW->lastseq=0; IW->mode=IW_TEXTMODE; return; // ^O

				case 24      : // Control X cancels any unprinted characters in the buffer.
                       // for now we're gonna ignore this.  We can implement it later, but
                       // our IW model is that we print all we receive as we receive it.
                       // We'll implement this if it's found that it's used by real software.
	               // Note that the Lisa sends a bunch of these before every print job to
	               // flush any jobs in the buffer...  Shouldn't affect us at all.
					IW->lastseq=0; IW->mode=IW_TEXTMODE; return;

				default: iw_printchar(IW,c); return;


			}
		case IW_TEXT_0X1D : // TOP of FORM for setting vertical tabs is 0x1d 0x41 0x40 -- not sure how this should be...
			if ( c==65 && IW->submode==0) {IW->submode=1; IW->submode1=0; iw_settopofform(IW);return;       }
			if ( c==64 && IW->submode==1)
			{IW->submode=2; IW->submode1=0; IW->submode2=0; IW->submode3=0; IW->submode4=-1; return; }

			page=IW->submode3;
			line=IW->submode4+1;

			if (IW->submode==2)
			{
				if (IW->submode2==0) {IW->submode2=c; return;}

				c2=IW->submode2; IW->submode2=0; IW->submode3=0;

				if (c=='@' && c2=='@') {IW->vtabs[page][line][0]=0; IW->vtabs[page][line][1]=0; IW->vtabs[page][line][2]=0;
					IW->vtabs[page][line][3]=0; IW->vtabs[page][line][4]=0;  IW->submode3=page; IW->submode4=line; return;}  // sets no tabs

				if (c=='B' && c2=='@') {IW->vtabs[page][line][0]=1;                  IW->submode3=page; IW->submode4=line; return;}  // sets tab B
				if (c=='D' && c2=='@') {IW->vtabs[page][line][1]=1;                  IW->submode3=page; IW->submode4=line; return;}  // sets tab C
				if (c=='H' && c2=='@') {IW->vtabs[page][line][2]=1;                  IW->submode3=page; IW->submode4=line; return;}  // sets tab D
				if (c=='P' && c2=='@') {IW->vtabs[page][line][3]=1;                  IW->submode3=page; IW->submode4=line; return;}  // sets tab E
				if (c==96  && c2=='@') {IW->vtabs[page][line][4]=1;                  IW->submode3=page; IW->submode4=line; return;}  // sets tab F '

				if (c=='F' && c2=='@') {IW->vtabs[page][line][0]=1; IW->vtabs[page][line][1]=1;  IW->submode3=page; IW->submode4=line; return;}  // B&C
				if (c=='J' && c2=='@') {IW->vtabs[page][line][0]=1; IW->vtabs[page][line][2]=1;  IW->submode3=page; IW->submode4=line; return;}  // B&D
				if (c=='R' && c2=='@') {IW->vtabs[page][line][0]=1; IW->vtabs[page][line][3]=1;  IW->submode3=page; IW->submode4=line; return;}  // B&E
				if (c=='b' && c2=='@') {IW->vtabs[page][line][1]=1; IW->vtabs[page][line][4]=1;  IW->submode3=page; IW->submode4=line; return;}  // B&F

				if (c=='L' && c2=='@') {IW->vtabs[page][line][1]=1; IW->vtabs[page][line][2]=1;  IW->submode3=page; IW->submode4=line; return;}  // C&D
				if (c=='T' && c2=='@') {IW->vtabs[page][line][1]=1; IW->vtabs[page][line][3]=1;  IW->submode3=page; IW->submode4=line; return;}  // C&E
				if (c=='d' && c2=='@') {IW->vtabs[page][line][1]=1; IW->vtabs[page][line][4]=1;  IW->submode3=page; IW->submode4=line; return;}  // C&F

				if (c=='X' && c2=='@') {IW->vtabs[page][line][2]=1; IW->vtabs[page][line][3]=1;  IW->submode3=page; IW->submode4=line; return;}  // D&E
				if (c=='h' && c2=='@') {IW->vtabs[page][line][2]=1; IW->vtabs[page][line][4]=1;  IW->submode3=page; IW->submode4=line; return;}  // D&E

				if (c=='p' && c2=='@') {IW->vtabs[page][line][3]=1; IW->vtabs[page][line][4]=1;  IW->submode3=page; IW->submode4=line; return;}  // E&F

				if (c=='N' && c2=='@') {IW->vtabs[page][line][0]=1; IW->vtabs[page][line][1]=1; IW->vtabs[page][line][2]=1; IW->submode3=page; IW->submode4=line; return;}  // BCD
				if (c=='V' && c2=='@') {IW->vtabs[page][line][0]=1; IW->vtabs[page][line][1]=1; IW->vtabs[page][line][3]=1; IW->submode3=page; IW->submode4=line; return;}  // BCE
				if (c=='f' && c2=='@') {IW->vtabs[page][line][0]=1; IW->vtabs[page][line][1]=1; IW->vtabs[page][line][4]=1; IW->submode3=page; IW->submode4=line; return;}  // BCF
				if (c=='Z' && c2=='@') {IW->vtabs[page][line][0]=1; IW->vtabs[page][line][2]=1; IW->vtabs[page][line][3]=1; IW->submode3=page; IW->submode4=line; return;}  // BDE
				if (c=='j' && c2=='@') {IW->vtabs[page][line][0]=1; IW->vtabs[page][line][2]=1; IW->vtabs[page][line][4]=1; IW->submode3=page; IW->submode4=line; return;}  // BDF

				if (c=='j' && c2=='@') {IW->vtabs[page][line][0]=1; IW->vtabs[page][line][2]=1; IW->vtabs[page][line][4]=1; IW->submode3=page; IW->submode4=line; return;}  // BDF
				if (c=='r' && c2=='@') {IW->vtabs[page][line][0]=1; IW->vtabs[page][line][3]=1; IW->vtabs[page][line][4]=1; IW->submode3=page; IW->submode4=line; return;}  // BEF
				if (c==92  && c2=='@') {IW->vtabs[page][line][1]=1; IW->vtabs[page][line][2]=1; IW->vtabs[page][line][3]=1; IW->submode3=page; IW->submode4=line; return;}  // CDE
				if (c==108 && c2=='@') {IW->vtabs[page][line][1]=1; IW->vtabs[page][line][2]=1; IW->vtabs[page][line][4]=1; IW->submode3=page; IW->submode4=line; return;}  // CDF
				if (c==116 && c2=='@') {IW->vtabs[page][line][1]=1; IW->vtabs[page][line][3]=1; IW->vtabs[page][line][4]=1; IW->submode3=page; IW->submode4=line; return;}  // CEF

				if (c==94  && c2=='@') {IW->vtabs[page][line][0]=1; IW->vtabs[page][line][1]=1; IW->vtabs[page][line][2]=1;
					IW->vtabs[page][line][3]=1;
					IW->submode3=page; IW->submode4=line; return;}  // BCDE

				if (c==110 && c2=='@') {IW->vtabs[page][line][0]=1; IW->vtabs[page][line][1]=1; IW->vtabs[page][line][2]=1;
					IW->vtabs[page][line][4]=1;
					IW->submode3=page; IW->submode4=line; return;}  // BCDF

				if (c==118 && c2=='@') {IW->vtabs[page][line][0]=1; IW->vtabs[page][line][1]=1; IW->vtabs[page][line][3]=1;
					IW->vtabs[page][line][4]=1;
					IW->submode3=page; IW->submode4=line; return;}  // BCEF

				if (c==122 && c2=='@') {IW->vtabs[page][line][0]=1; IW->vtabs[page][line][2]=1; IW->vtabs[page][line][3]=1;
					IW->vtabs[page][line][4]=1;
					IW->submode3=page; IW->submode4=line; return;}  // BDEF

				if (c==126 && c2=='@') {IW->vtabs[page][line][0]=1; IW->vtabs[page][line][1]=1; IW->vtabs[page][line][2]=1;
					IW->vtabs[page][line][3]=1; IW->vtabs[page][line][4]=1;
					IW->submode3=page; IW->submode4=line; return;}  // BCDEF


				if (c=='C' && c2=='@') {// set bottom of form
					IW->vtabs[page][line][5]=1;
					IW->submode3=page; IW->submode4=line; return;}



				if (c=='A' && c2=='@') {// A@(Control-) (30 or 0x1e) set next page;
					IW->submode3=page; IW->submode4=line; return;}

				if (c==0x1e) {IW->submode3=page; IW->submode4=line; return;}  // eat control - from A@^- this is cheating, I know.



			}


		case  IW_TEXT_CTRLUL:

			if (c>='A' && c<='F')
			{
				if ( c=='A') c='G';
				c-='B';
				for (i=0; i<96; i++)
					if (IW->vtabs[page][i][c])
					{ iw_set_vline_pos(IW,i);
						IW->mode=IW_TEXTMODE; IW->submode1=0;IW->submode2=0;IW->submode3=0;IW->submode4=0;
						return; }
                    // at this point, we didn't find what we were looking for, so we have to jump to next BOF.
				for (i=0; i<96; i++)
					if (IW->vtabs[page][i][5])
					{ iw_set_vline_pos(IW,i);
						IW->mode=IW_TEXTMODE; IW->submode1=0;IW->submode2=0;IW->submode3=0;IW->submode4=0;
						return; }

                    // we didn't find the next BOF, we go to the next page
                if (IW->debug) DEBUG_LOG(0,"FF via CONTROL_ (bottom of form)\n");
				iw_formfeed(IW);
				IW->mode=IW_TEXTMODE; IW->submode1=0;IW->submode2=0;IW->submode3=0;IW->submode4=0;
				return;
			}
			IW->mode=IW_TEXTMODE; IW->submode1=0;IW->submode2=0;IW->submode3=0;IW->submode4=0; return;

  /* case IW_TEXT_GS:                      // set vertical tabs to power on status, TOF to current position.
              if ( c=='0')
                 {
                  ***

                 }
*/
			IW->mode=IW_TEXTMODE; IW->submode1=0;IW->submode2=0;IW->submode3=0;IW->submode4=0; return;
		default:
			IW->mode=IW_TEXTMODE; IW->submode1=0;IW->submode2=0;IW->submode3=0;IW->submode4=0; return;
	}

}




#ifdef STANDALONE

/*
// This is here because the atof function on my copy of solaris 2.5.1 SPARC is buttfucked and will
// return bullshit answers.

double myatof(char *s)
{
	double v=0.0, vfrac=0.1, neg=1.0;
	char c, *p;

	p=s;

	if (*p=='-') neg=-1.0;

	while (*p>='0' && *p<='9') {v=(v*10.0)+((*p)-'0'); p++;} // get decimals.
	if (*p!='.') return (v*neg); else p++;
	while (*p>='0' && *p<='9') {v=v+(  ((*p)-'0')*vfrac ); p++; vfrac=vfrac/10.0;} // get decimals.
	return (v*neg);
}


int main(int argc, char *argv[])
{

	ImageWriterType IWX, *IW;
	FILE *job;

	char c;
	int32 i,j,count, percent, filesize;
	int8 processedjob=0, paperpixel=0;

	count=0;
	IW=&IWX;




  //                       1         2         3         4         5         6         7
  //              1234567890123456789012345678901234567890123456789012345678901234567890123456789
    DEBUG_LOG(0,"\n Apple ImageWriter I Emulator %s - part of the Lisa Emulation Project\n",VERSION);
    DEBUG_LOG(0,"      Copyright (C) 1998 by Ray Arsen Arachelian, All Rights Reserved.\n\n");

	for (i=0; i<argc; i++)
		if (strlen(argv[i])>128)
		{
            DEBUG_LOG(0,"Hey babe, you tryin\' to blow my buffers? Ooh, that feels soooo gooood!\n");
			system("echo 'Hi, I\'m trying to overflow IW_EMU\'s buffers.  Please spank my ass hard and make it hurt!' | mail root");
			exit(2);
		}

	if (argc<3 && argc!=1)
	{//                       1         2         3         4         5         6         7
  //              1234567890123456789012345678901234567890123456789012345678901234567890123456789

        fflush(buglog);

        DEBUG_LOG(0,"usage %s {options} job job... job   or  someprogram | %s --\n",argv[0],argv[0]);
        DEBUG_LOG(0,"i.e   %s -ps -pcl myjob.iw          or  cat myjob.iw | %s -ps  --\n\n",argv[0],argv[0]);
        DEBUG_LOG(0,"      job is the name of a file.  If -- is used, I will assume stdin.\n\n");
        DEBUG_LOG(0,"      options: -ps   : will output Adobe PostScript file(s)\n");
        DEBUG_LOG(0,"               -pcl  : will output Hewlett-Packard PCL file(s)\n");
        DEBUG_LOG(0,"               -xlib : will output to the current X display.\n");
        DEBUG_LOG(0,"      * At least one output must be chosen.\n\n");
        DEBUG_LOG(0,"               -pixx:value    horizontal size of paper in pixels.\n");
        DEBUG_LOG(0,"               -pixy:value    vertical   size of paper in pixels.\n\n");
        DEBUG_LOG(0,"               -paperx:value  horizontal size of paper in inches.\n");
        DEBUG_LOG(0,"               -papery:value  vertical   size of paper in inches.\n\n");
        DEBUG_LOG(0,"               -dpi:value     Output DPI (Supported by PCI)    \n\n");

// These shouldn't be used by the user.
//  DEBUG_LOG(0,"               -dpiw:value    horizontal Dots Per Inch (72,160)\n\n");
//  DEBUG_LOG(0,"               -dpih:value    vertical   Dots Per Inch (72,144)\n\n");

        DEBUG_LOG(0,"               -dipsw1:value  dip switch settings bank1 \n");
        DEBUG_LOG(0,"               -dipsw2:value  dip switch settings bank2 \n");
        DEBUG_LOG(0," dips1 and dipsw2 values are numerical representations of the dipswitches.\n");
        DEBUG_LOG(0," dipsw1 is 210 if not specified. (Default for USA)  dipsw2 is ignored.\n");
        DEBUG_LOG(0," Note: you can't use both -pix?:value and -paper?:value options.\n");
        DEBUG_LOG(0,"       No spaces allowed after option requring a value.\n");
        DEBUG_LOG(0,"       i.e.: -dipsw:210 is ok,  -dipsw: 210 is not.\n\n");
        DEBUG_LOG(0," DIP Switches Values:\n\
   see: http://alt-www.corvis.ru/html/tech/Printers/upm/printers/mapiw.htm\n\
   (if you can get a good connection to it.) or your ImageWriter manual.\n\
   \n\
   Country Font Selection: (Can be software overridden)\n\
   \n\
   DIP SWITCH Bank One.\n\
   \n\
        bit (bit 1=2^0, bit 2 is 2^1, bit 3 is 2^2)\n\
        1,2,3     Effect.         Software Setting for the same:\n\
        000       American Font.    ESC Z,^G,^@\n\
        110       British  Font.    ESC Z,^D,^@,ESC D,^C,^@\n\
        001       German   Font.    ESC Z,^C,^@,ESC D,^D,^@\n\
        011       French   Font.    ESC Z,^A,^@,ESC D,^F,^@\n\
        101       Sweedish Font.    ESC Z,^B,^@,ESC D,^E,^@\n\
        100       Italian  Font.    ESC Z,^F,^@,ESC D,^A,^@\n\
        111       Spanish  Font.    ESC D,^G,^@\n\
        010       American Font 2.  ESC Z,^E,^@,ESC D,^B,^@\n\
\n\
        bit 4-    72 lines (on) 66 lines (off)\n\
        bit 5-    If on, AND all data with 127 (strip 8th bit)\n\
\n\
        bit 6,7\n\
        00        Elite Proportional (upto 160dpi)\n\
        01        Elite          12cpi\n\
        10        Ultracondensed 17cpi\n\
        11        Pica           10cpi\n\
\n\
        bit-8     Auto Line Feed. 1=on (auto LF after CR)     , 0=off (requires LF char)\n\
\n\
   DIP Switch Bank Two\n\
\n\
        bits1,2\n\
        00       9600 bps serial connection (we ignore the connection here.)\n\
        01       1200 bps serial connection (we ignore the connection here.)\n\
        10       2400 bps serial connection (we ignore the connection here.)\n\
        11       300  bps serial connection (we ignore the connection here.)\n\
\n\
\n\
        bit3 -   handshake:  0= Xon/Xoff, 1=Hardware handshake. (We ignore this too.)\n\
\n\
        bit4-8   ignored.\n\n");



		exit(3);
	}

	IW->debug=0;
	IW->argc=argc;
	IW->argv=argv;
	IW->xlib_skip=0;

	IW->outputps=0;
	IW->outputpcl=0;
	IW->outputxlib=0;
	IW->currentVCPIdiv=2;
	IW->dipsw1=210; IW->dipsw2=0;
	IW->landscape=0;

	IW->scalex=0;
	IW->scaley=0;          // Scaling factors for output
	IW->outmaxx=0;
	IW->outmaxy=0;
	IW->outputdpi=0;;           // Maximum size of output page, output page DPI.


// These used to be defines, but they're better off as variables.

	IW->iw_def_dpi        = DIW_DEF_DPI         ;
	IW->iw_max_hdpi       = DIW_MAX_HDPI        ;
	IW->iw_max_wdpi       = DIW_MAX_WDPI        ;
	IW->iw_paper_w        = DIW_PAPER_W         ;
	IW->iw_paper_h        = DIW_PAPER_H         ;
	IW->iw_max_x          = DIW_MAX_X           ;
	IW->iw_max_y          = DIW_MAX_Y           ;
	IW->iw_bitsperpixel   = DIW_BITS_PER_PIXEL  ;
	IW->iw_bytes_per_line = DIW_BYTES_PER_HLINE ;


	for (i=1; i<argc-1; i++)
	{

		if (strcmp(argv[i],"-ps")==0)
		{
#ifdef POSTSCRIPT
			IW->outputps=1;
#else
            DEBUG_LOG(0,"I'm terribly sorry, but whomever compiled this code disabled Adobe PostScript output.\n"); exit(99);
#endif
		}

		if (strcmp(argv[i],"-pcl")==0)
		{
#ifdef PCL
			IW->outputpcl=1;
#else
            DEBUG_LOG(0,"I'm terribly sorry, but whomever compiled this code disabled HP PCL output.\n"); exit(99);
#endif

		}
		if (strcmp(argv[i],"-xlib")==0)
		{
#ifdef XLIB
			IW->outputxlib=1;
#else
            DEBUG_LOG(0,"I'm terribly sorry, but whomever compiled this code disabled Xlib display output.\n"); exit(99);
#endif
		}

// These used to be defines, but they're better off as variables.


		if (strstr(argv[i],"-dpi:")!=0)    {IW->outputdpi       =atol(&argv[i][5]);
			IW->iw_max_x=IW->iw_max_wdpi * IW->iw_paper_w; IW->iw_max_y=IW->iw_max_hdpi * IW->iw_paper_h; IW->iw_bytes_per_line=IW->iw_max_x/2;
            if (IW->iw_max_wdpi<72 || IW->iw_max_wdpi>160) DEBUG_LOG(0,"Warning! DPIW specified (%ld) are out of range!\n",IW->iw_max_wdpi); }


// These two should never be used by the user !

		if (strstr(argv[i],"-dpiw:")!=0)    {IW->iw_max_wdpi  =atol(&argv[i][6]);
			IW->iw_max_x=IW->iw_max_wdpi * IW->iw_paper_w; IW->iw_max_y=IW->iw_max_hdpi * IW->iw_paper_h; IW->iw_bytes_per_line=IW->iw_max_x/2;
            if (IW->iw_max_wdpi<72 || IW->iw_max_wdpi>160) DEBUG_LOG(0,"Warning! DPIW specified (%ld) are out of range!\n",IW->iw_max_wdpi); }

		if (strstr(argv[i],"-dpih:")!=0)    {IW->iw_max_hdpi  =atol(&argv[i][6]);
			IW->iw_max_x=IW->iw_max_wdpi * IW->iw_paper_w; IW->iw_max_y=IW->iw_max_hdpi * IW->iw_paper_h; IW->iw_bytes_per_line=IW->iw_max_x/2;
			IW->currentVCPIdiv=2*144/IW->iw_max_hdpi; if (!IW->currentVCPIdiv) IW->currentVCPIdiv=2;
            if (IW->iw_max_hdpi<72 || IW->iw_max_hdpi>160) DEBUG_LOG(0,"Warning! DPIH specified (%ld) are out of range!\n",IW->iw_max_hdpi); }




		if (strstr(argv[i],"-paperx:")!=0) {IW->iw_paper_w  =myatof(&argv[i][8]);  paperpixel=paperpixel | 1;
            if (IW->iw_paper_h>17.8 || IW->iw_paper_w>11.9 ) {DEBUG_LOG(0,"That's a bit too big a sheet of paper, don't you think?\n"); exit(55);}
            if (IW->iw_paper_h<0    || IW->iw_paper_w<0    ) {DEBUG_LOG(0,"Hmmm, negative sized paper, that's a good one... Heh!\n"); exit(55);}
		}

		if (strstr(argv[i],"-papery:")!=0) {IW->iw_paper_h  =myatof(&argv[i][8]);  paperpixel=paperpixel | 1;
            if (IW->iw_paper_h>17.8 || IW->iw_paper_w>11.9 ) {DEBUG_LOG(0,"That's a bit too big a sheet of paper, don't you think?\n"); exit(55);}
            if (IW->iw_paper_h<0    || IW->iw_paper_w<0    ) {DEBUG_LOG(0,"Hmmm, negative sized paper, that's a good one... Heh!\n"); exit(55);}
		}

		if (strstr(argv[i],"-pixx:")!=0)   {IW->iw_max_x    =atol(&argv[i][6]);  paperpixel=paperpixel | 2; }

		if (strstr(argv[i],"-pixy:")!=0)   {IW->iw_max_y    =atol(&argv[i][6]);  paperpixel=paperpixel | 2; }

		if (strstr(argv[i],"-xskip:")!=0)   {IW->xlib_skip  =atoi(&argv[i][7]);  }



// Over-ride default behavior of ImageWriter priner
		if (strstr(argv[i],"-dipsw1:")!=0) { IW->dipsw1=atoi(&argv[i][8]); }
		if (strstr(argv[i],"-dipsw2:")!=0) { IW->dipsw2=atoi(&argv[i][8]); }

// Unsupported options.
		if (strcmp(argv[i],"-l")==0) { IW->landscape=1; }
        if (strcmp(argv[i],"-debug")==0) { IW->debug=1; DEBUG_LOG(0,"Debugging output enabled to stdout\n");}

	}

    if (IW->debug) DEBUG_LOG(0,"Checking for job\n");
 // make sure we're not just twiddling our thumbs
	if (! ((IW->outputps | IW->outputpcl) | IW->outputxlib))
	{
        DEBUG_LOG(0,"You must specify at least one output file type (i.e. -ps or -pcl or -xlib)\n");
        exit(181);
	}

	if (IW->outputdpi==0)
	{
		if (IW->outputps)   IW->outputdpi=72;
		if (IW->outputpcl)  IW->outputdpi=150;
		if (IW->outputxlib) IW->outputdpi=160;
	}

	IW->outmaxx=IW->outputdpi * IW->iw_paper_w;
	IW->outmaxy=IW->outputdpi * IW->iw_paper_h;

	IW->scalex=0.0;
	IW->scaley=0.0;


	IW->currentVCPIdiv=2*144/IW->iw_max_hdpi; if (!IW->currentVCPIdiv) IW->currentVCPIdiv=2;

    if (IW->debug) DEBUG_LOG(0,"Checking for pixel recalculations.\n");
 // Do the needed recalculations.
	if (paperpixel==1)
	{
		IW->iw_max_x=(uint32)((double)(IW->iw_max_wdpi) * (IW->iw_paper_w));
		IW->iw_max_y=(uint32)((double)(IW->iw_max_hdpi) * (IW->iw_paper_h));
		IW->iw_bytes_per_line=IW->iw_max_x/2;
        if (IW->debug) DEBUG_LOG(0,"paper: %ld %ld hdpi:%ld",(long  ) (IW->iw_paper_w),(long  ) (IW->iw_paper_h),IW->iw_max_hdpi);
        if (IW->debug) DEBUG_LOG(0,"pixls: %ld %ld wdpi:%ld",(long  ) (IW->iw_max_x  ),(long  ) (IW->iw_max_y  ),IW->iw_max_wdpi);
	}

    if (IW->debug) DEBUG_LOG(0,"Checking for paper recalculations.\n");

	if (paperpixel==2)
	{
		IW->iw_paper_w=(double) (IW->iw_max_x/IW->iw_max_wdpi);
		IW->iw_paper_h=(double) (IW->iw_max_y/IW->iw_max_hdpi);
		IW->iw_bytes_per_line=IW->iw_max_x/2;
	}


	IW->scalex=(float) ((float) IW->outmaxx/(float)(IW_MAX_X));
	IW->scaley=(float) ((float) IW->outmaxy/(float)(IW_MAX_Y));


    if (IW->debug) DEBUG_LOG(0,"Checking for both -paper and -pix.\n");
	if (paperpixel==3)
	{
        DEBUG_LOG(0,"I'm sorry, but you can't use both -pix?: and -paper?: at the same time.\n");
        exit(182);
	}



    if (IW->debug) DEBUG_LOG(0,"Allocating page buffer memory.\n");
 // Allocate an image buffer.
    if (iw_malloc(IW)) {DEBUG_LOG(0,"Couldn\'t allocate memory\n"); exit(183);}


    if (IW->debug) DEBUG_LOG(0,"IWDPI %d,%d vcpidiv %d  paperx %d ,papery %d.\n",IW->iw_max_wdpi,IW->iw_max_hdpi,IW->currentVCPIdiv,IW_MAX_X,IW_MAX_Y);


	processedjob=0;

    if (IW->debug) DEBUG_LOG(0,"Processing Jobs.\n");
	for (i=1; i<argc; i++)
	{
		if (argv[i][0]=='-') // are we getting an option or -- ?
		{
			if (argv[i][1]=='-')  // if -- assume job comes from stdin.
			{
                if (IW->debug) DEBUG_LOG(0,"Initializing printer.\n");
				iw_initialize(IW);           // setup settings from dip switch settings, etc...
				job=stdin;
				count=0;
				while (!feof(job))  {c=fgetc(job); ImageWriterLoop(IW,c); count++; if (!(count & 0x1f)) twirly();  }
				if (c!=12) iw_formfeed(IW);
				if (job!=stdin) fclose(job);
                DEBUG_LOG(0,"Processed: %ld bytes of IW code from stdin\n",count);
				processedjob++;
			}

		}
		else
		{    job=fopen(argv[i],"rb");
            if (!job) {DEBUG_LOG(0,"parameter #%d, %s\n",i,argv[i]);perror("IW_EMU: Sorry, I couldn't open specified print job file\n"); }
			else
			{
				fseek(job,0,SEEK_END);
				filesize=ftell(job);
				fseek(job,0,SEEK_SET);
				count=0;
                if (IW->debug) DEBUG_LOG(0,"Initializing printer.\n");
				iw_initialize(IW);           // setup settings from dip switch settings, etc...
				while (count<=filesize)
				{fread(&c,1,1,job); ImageWriterLoop(IW,c); count++;
					if (!(count &0x1f) && (job!=stdin) )   { percent=100*count/filesize; thermometer("IW Render Job",percent); }
				}
                if (IW->debug) DEBUG_LOG(0,"End of Job at %ld of %ld\n",count,filesize);
                fflush(buglog); fflush(stdout);
				iw_formfeed(IW);
				if (job!=stdin) {fclose(job); job=NULL;}
                thermometer("IW Render Job",100); DEBUG_LOG(0,"\n");
                DEBUG_LOG(0,"Processed: %ld bytes of IW code from %s\n",count,argv[i]);
				processedjob++;
			}
		}
	}

    if (processedjob>1) DEBUG_LOG(0,"Processed %d jobs\n\n",processedjob);
    else if (processedjob==1) DEBUG_LOG(0,"Processed 1 job\n\n");
    else DEBUG_LOG(0,"\n");

	exit(0);
}
*/
#else



#ifdef INLISAEM



int ImageWriter_LisaEm_Init(ImageWriterType *IW, int pcl, int ps, int xlib)
{

    //ImageWriterType IWX;
	//FILE *job;
	//char c;
    //int8 processedjob=0;
	//int32 percent, filesize, i, j;
	
	int32 count; 
	int8 paperpixel=0;


    ALERT_LOG(0,"Initializing ImageWriter");

	count=0;
    //IW=&IWX;


    IW->outputps=ps;
    IW->outputpcl=pcl;
    IW->outputxlib=xlib;


	IW->debug=0;
    IW->argc=0;
    IW->argv=NULL;
	IW->xlib_skip=0;

	IW->currentVCPIdiv=2;
	IW->dipsw1=210; IW->dipsw2=0;
	IW->landscape=0;

	IW->scalex=0;
	IW->scaley=0;          // Scaling factors for output
	IW->outmaxx=0;
	IW->outmaxy=0;
	IW->outputdpi=0;;           // Maximum size of output page, output page DPI.


// These used to be defines, but they're better off as variables.

	IW->iw_def_dpi        = DIW_DEF_DPI         ;
	IW->iw_max_hdpi       = DIW_MAX_HDPI        ;
	IW->iw_max_wdpi       = DIW_MAX_WDPI        ;
	IW->iw_paper_w        = DIW_PAPER_W         ;
	IW->iw_paper_h        = DIW_PAPER_H         ;
	IW->iw_max_x          = DIW_MAX_X           ;
	IW->iw_max_y          = DIW_MAX_Y           ;
	IW->iw_bitsperpixel   = DIW_BITS_PER_PIXEL  ;
	IW->iw_bytes_per_line = DIW_BYTES_PER_HLINE ;



	IW->iw_max_x=IW->iw_max_wdpi * IW->iw_paper_w; IW->iw_max_y=IW->iw_max_hdpi * IW->iw_paper_h; IW->iw_bytes_per_line=IW->iw_max_x/2;
	IW->landscape=0;




	if (IW->outputdpi==0)
	{
        if (IW->outputps)   IW->outputdpi=144; //72;
		if (IW->outputpcl)  IW->outputdpi=150;
		if (IW->outputxlib) IW->outputdpi=160;
	}

	IW->outmaxx=IW->outputdpi * IW->iw_paper_w;
	IW->outmaxy=IW->outputdpi * IW->iw_paper_h;

	IW->scalex=0.0;
	IW->scaley=0.0;


	IW->currentVCPIdiv=2*144/IW->iw_max_hdpi; if (!IW->currentVCPIdiv) IW->currentVCPIdiv=2;

    if (paperpixel==3) paperpixel=1;

    if (paperpixel==1)
	{
		IW->iw_max_x=(uint32)((double)(IW->iw_max_wdpi) * (IW->iw_paper_w));
		IW->iw_max_y=(uint32)((double)(IW->iw_max_hdpi) * (IW->iw_paper_h));
		IW->iw_bytes_per_line=IW->iw_max_x/2;
        if (IW->debug) DEBUG_LOG(0,"paper: %ld %ld hdpi:%ld",(long  ) (IW->iw_paper_w),(long  ) (IW->iw_paper_h),IW->iw_max_hdpi);
        if (IW->debug) DEBUG_LOG(0,"pixls: %ld %ld wdpi:%ld",(long  ) (IW->iw_max_x  ),(long  ) (IW->iw_max_y  ),IW->iw_max_wdpi);
	}


	if (paperpixel==2)
	{
		IW->iw_paper_w=(double) (IW->iw_max_x/IW->iw_max_wdpi);
		IW->iw_paper_h=(double) (IW->iw_max_y/IW->iw_max_hdpi);
		IW->iw_bytes_per_line=IW->iw_max_x/2;
	}


	IW->scalex=(float) ((float) IW->outmaxx/(float)(IW_MAX_X));
	IW->scaley=(float) ((float) IW->outmaxy/(float)(IW_MAX_Y));

    iw_initialize(IW);           // setup settings from dip switch settings, etc...

    ALERT_LOG(0,"Allocated %d bytes for page:%p for IW:%p",IW->pagesize,IW->page,IW);



    //while (!feof(job))  {c=fgetc(job); ImageWriterLoop(IW,c); count++; if (!(count & 0x1f)) twirly();  }
    //            if (c!=12) iw_formfeed(IW);
    //            if (job!=stdin) fclose(job);
    //            DEBUG_LOG(0,"Processed: %ld bytes of IW code from stdin\n",count);
    //            processedjob++;
    //        }


   return 0;
    /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
}



int xxxLisaEm_IWInit(ImageWriterType *IW, int argc, char **argv)
{

	//ImageWriterType IWX;
	//FILE *job;
	//char c;
	//int32 percent, filesize, i, j;
    int32 count;
	int8 processedjob=0, paperpixel=0;

	count=0;

    IW->debug=0;
	IW->argc=argc;
	IW->argv=argv;
	IW->xlib_skip=0;

	IW->outputps=0;
	IW->outputpcl=0;
	IW->outputxlib=0;
	IW->currentVCPIdiv=2;
	IW->dipsw1=210; IW->dipsw2=0;
	IW->landscape=0;

	IW->scalex=0;
	IW->scaley=0;          // Scaling factors for output
	IW->outmaxx=0;
	IW->outmaxy=0;
	IW->outputdpi=0;;           // Maximum size of output page, output page DPI.


// These used to be defines, but they're better off as variables.

	IW->iw_def_dpi        = DIW_DEF_DPI         ;
	IW->iw_max_hdpi       = DIW_MAX_HDPI        ;
	IW->iw_max_wdpi       = DIW_MAX_WDPI        ;
	IW->iw_paper_w        = DIW_PAPER_W         ;
	IW->iw_paper_h        = DIW_PAPER_H         ;
	IW->iw_max_x          = DIW_MAX_X           ;
	IW->iw_max_y          = DIW_MAX_Y           ;
	IW->iw_bitsperpixel   = DIW_BITS_PER_PIXEL  ;
	IW->iw_bytes_per_line = DIW_BYTES_PER_HLINE ;


	IW->iw_max_x=IW->iw_max_wdpi * IW->iw_paper_w; IW->iw_max_y=IW->iw_max_hdpi * IW->iw_paper_h; IW->iw_bytes_per_line=IW->iw_max_x/2;
	IW->landscape=0;

	//for (i=0; i<argc; i++)
	//{
//
//
 //       if (strcmp(ARGV[(i)],"-debug")==0) { IW->debug=1; DEBUG_LOG(0,"Debugging output enabled to stdout\n");}
//
//	}

    if (IW->debug) DEBUG_LOG(0,"Checking for job\n");
 // make sure we're not just twiddling our thumbs
	if (! ((IW->outputps | IW->outputpcl) | IW->outputxlib))
	{
        DEBUG_LOG(0,"You must specify at least one output file type (i.e. -ps or -pcl or -xlib)\n");
        exit(184);
	}

	if (IW->outputdpi==0)
	{
		if (IW->outputps)   IW->outputdpi=72;
		if (IW->outputpcl)  IW->outputdpi=150;
		if (IW->outputxlib) IW->outputdpi=160;
	}

	IW->outmaxx=IW->outputdpi * IW->iw_paper_w;
	IW->outmaxy=IW->outputdpi * IW->iw_paper_h;

	IW->scalex=0.0;
	IW->scaley=0.0;


	IW->currentVCPIdiv=2*144/IW->iw_max_hdpi; if (!IW->currentVCPIdiv) IW->currentVCPIdiv=2;

    if (IW->debug) DEBUG_LOG(0,"Checking for pixel recalculations.\n");
 // Do the needed recalculations.
	if (paperpixel==1)
	{
		IW->iw_max_x=(uint32)((double)(IW->iw_max_wdpi) * (IW->iw_paper_w));
		IW->iw_max_y=(uint32)((double)(IW->iw_max_hdpi) * (IW->iw_paper_h));
		IW->iw_bytes_per_line=IW->iw_max_x/2;
        if (IW->debug) DEBUG_LOG(0,"paper: %ld %ld hdpi:%ld",(long  ) (IW->iw_paper_w),(long  ) (IW->iw_paper_h),IW->iw_max_hdpi);
        if (IW->debug) DEBUG_LOG(0,"pixls: %ld %ld wdpi:%ld",(long  ) (IW->iw_max_x  ),(long  ) (IW->iw_max_y  ),IW->iw_max_wdpi);
	}

    if (IW->debug) DEBUG_LOG(0,"Checking for paper recalculations.\n");

	if (paperpixel==2)
	{
		IW->iw_paper_w=(double) (IW->iw_max_x/IW->iw_max_wdpi);
		IW->iw_paper_h=(double) (IW->iw_max_y/IW->iw_max_hdpi);
		IW->iw_bytes_per_line=IW->iw_max_x/2;
	}


	IW->scalex=(float) ((float) IW->outmaxx/(float)(IW_MAX_X));
	IW->scaley=(float) ((float) IW->outmaxy/(float)(IW_MAX_Y));


    if (IW->debug) DEBUG_LOG(0,"Checking for both -paper and -pix.\n");
	if (paperpixel==3)
	{
        DEBUG_LOG(0,"I'm sorry, but you can't use both -pix?: and -paper?: at the same time.\n");
        exit(185);
	}



    if (IW->debug) DEBUG_LOG(0,"Allocating page buffer memory.\n");
 // Allocate an image buffer.
    if (iw_malloc(IW)) {DEBUG_LOG(0,"Couldn\'t allocate memory for an Imagewriter output page\n"); exit(186);}


    if (IW->debug) DEBUG_LOG(0,"IWDPI %d,%d vcpidiv %d  paperx %d ,papery %d.\n",IW->iw_max_wdpi,IW->iw_max_hdpi,IW->currentVCPIdiv,IW_MAX_X,IW_MAX_Y);


	processedjob=0;
/****** 20061210
    if (IW->debug) DEBUG_LOG(0,"Processing Jobs.\n");
	for (i=1; i<argc; i++)
	{
		if (ARGV[i][0]=='-') // are we getting an option or -- ?
		{
			if (ARGV[i][1]=='-')  // if -- assume job comes from stdin.
			{
                if (IW->debug) DEBUG_LOG(0,"Initializing printer.\n");
				iw_initialize(IW);           // setup settings from dip switch settings, etc...
				job=stdin;
				count=0;
				while (!feof(job))  {c=fgetc(job); ImageWriterLoop(IW,c); count++; if (!(count & 0x1f)) twirly();  }
				if (c!=12) iw_formfeed(IW);
				if (job!=stdin) fclose(job);
                DEBUG_LOG(0,"Processed: %ld bytes of IW code from stdin\n",count);
				processedjob++;
			}

		}
		else
		{    job=fopen(ARGV[i],"rb");
			if (!job)
            {DEBUG_LOG(0,"parameter #%d, %s\n",i,ARGV[i]);
				perror("IW_EMU: Sorry, I couldn't open specified print job file\n"); }
			else
			{
				fseek(job,0,SEEK_END);
				filesize=ftell(job);
				fseek(job,0,SEEK_SET);
				count=0;
                if (IW->debug) DEBUG_LOG(0,"Initializing printer.\n");
				iw_initialize(IW);           // setup settings from dip switch settings, etc...
				while (count<=filesize)
				{fread(&c,1,1,job); ImageWriterLoop(IW,c); count++;
					if (!(count &0x1f) && (job!=stdin) )   { percent=100*count/filesize; thermometer("IW Render Job",percent); }
				}
                if (IW->debug) DEBUG_LOG(0,"End of Job at %ld of %ld\n",count,filesize);
                fflush(buglog); fflush(stdout);
				iw_formfeed(IW);
				if (job!=stdin) {fclose(job); job=NULL;}
                thermometer("IW Render Job",100); DEBUG_LOG(0,"\n");
                DEBUG_LOG(0,"Processed: %ld bytes of IW code from %s\n",count,ARGV[i]);
				processedjob++;
			}
		}
	}

*/

    if (processedjob>1) {DEBUG_LOG(0,"Processed %d jobs\n\n",processedjob);}
    else if (processedjob==1) {DEBUG_LOG(0,"Processed 1 job\n\n");}
    else {DEBUG_LOG(0,"\n");}

	return 0;

}


#endif


/******************* To invoke this as a library *********************************************

 To initialize the printer:

   ImageWriterType IW; // (or: if ( (IW=malloc(sizeof(ImageWriterType)==NUL) screambloodymurder();  )

   IW->debug=0;
   IW->argc=argc;
   IW->argv=argv;

   IW->outputps=0;       // turn one of these on.
   IW->outputpcl=0;
   IW->outputxlib=0;

   IW->dipsw1=210; IW->dipsw2=0;
   IW->landscape=0;

   // These used to be defines, but they're better off as variables.

   IW->iw_def_dpi        = DIW_DEF_DPI         ;
   IW->iw_max_hdpi       = DIW_MAX_HDPI        ;
   IW->iw_max_wdpi       = DIW_MAX_WDPI        ;
   IW->iw_paper_w        = DIW_PAPER_W         ;
   IW->iw_paper_h        = DIW_PAPER_H         ;
   IW->iw_max_x          = DIW_MAX_X           ;
   IW->iw_max_y          = DIW_MAX_Y           ;
   IW->iw_bitsperpixel   = DIW_BITS_PER_PIXEL  ;
   IW->iw_bytes_per_line = DIW_BYTES_PER_HLINE ;


   // This next line allocates memory for a page.  You must use malloc since the IW structure can't hold such a huge array.
   if (iw_malloc(IW)) {DEBUG_LOG(0,"Couldn't allocate memory\n"); exit(1);}
   IW->dipsw1=242; IW->dipsw2=0;
   iw_initialize(IW);


 To send a printjob, setup a loop like this:

   for (i=0; i<printjobsize; i++) ImageWriterLoop(IW,printjob[c]);

 To send more jobs, be sure to re-initialize the printer first.


 And when you're done with the printer:

   free(IW->page); IW->page=NUL;  // if you malloc'ed IW add: free(IW); IW=NUL;



*********************************************************************************************/
#endif
