/*
 **************************************************************************
 *
 *       DoSpecial for HP_Deskjet_900C driver.
 *       By PJ Hutchison 1/11/01
 *
 **************************************************************************
 */

#include <exec/types.h>
#include <devices/printer.h>
#include <devices/prtbase.h>

#define LPI             9    /* Position in init.. string from 0 - 7 */
#define CPI             21
#define CHARSET         32
#define QUALITY         42
#define ASPECT          47   /* Portrait or Landscape */
#define TYPEFACE        52
#define INIT_LEN        54
#define LPP             10   /* Lines Per Page  */
#define FORM_LEN        14
#define LEFT_MARG       3
#define RIGHT_MARG      10
#define MARG_LEN        15

/* Version string */

const char __ver[39] = "$VER: HP_Deskjet_900C 40.13(15.06.02)";

/* Prototypes */

int DoSpecial(UWORD *cmd, char out[], BYTE *v, BYTE *c, BYTE *f, UBYTE p[]);
void numberString(UBYTE p, int x, char outputBuffer[]);
int ConvFunc(char *buf, char ch,int flag);
int Close(struct printerIO *ior);

/* Routine to handle complex Escape sequences */

DoSpecial(command, outputBuffer, vline, currentVMI, crlfFlag, Parms)
char outputBuffer[];
UWORD *command;
BYTE *vline;
BYTE *currentVMI;
BYTE *crlfFlag;
UBYTE Parms[];
{
        extern struct PrinterData *PD;
        extern struct PrinterExtendedData *PED;
       
        static UWORD textlength, topmargin;
        int x, y, j, papersize, lpi;

        static char initThisPrinter[INIT_LEN + 1] =
                "\033&l26A\033&l6D\033&d@\033(s0b10h0p0s12V\033(1E\033*v1S\033*o0M\033&l0O\033(s3T";
                
                /* 00-05 \033&l26A   = A4 Paper
                   06-10 \033&l6D    = 6 Lines per inch (LPI)
                   11-14 \033&d@     = Underline off
                   15-19 \033(s0b    = Normal weight (Bold off)
                   20-22      10h    = 10 chars per inch (CPI)
                   23-24       0p    = Fixed spacing
                   25-26       0s    = Upright style
                   27-29      12V    = 12 points/inch
                   30-33 \033(1E     = UK Char set (CHARSET)
                   34-38 \033*v1S    = Black text
                   39-43 \033*o0M    = Quality (QUALITY)
                   44-48 \033&l0O    = Portrait (ASPECT)
                   49-53 \033(s3T    = Typeface
                */
        static char initForm[FORM_LEN + 1] = "\033&l000E\033&l000F";
        static char initMarg[MARG_LEN + 1] = "\033&a000L\033&a000M\015";
        static char initTMarg[] = "\033&l000E\033&l000F";
       
        static char ISOColorTable[11] = "0102116881";

        x = y = j = 0;

        if (*command == aRIN) {         /* Initialise command */
                while(x < INIT_LEN) {
                        outputBuffer[x] = initThisPrinter[x];
                        x++;
                }
                outputBuffer[x++] = '\015';
                               
                lpi = 6;
                if (PD->pd_Preferences.PrintSpacing == EIGHT_LPI) {
                        outputBuffer[LPI] = '8';
                        lpi = 8;
                }

                if (PD->pd_Preferences.PrintPitch == ELITE) {
                        outputBuffer[CPI] = '2';
                }
                else if (PD->pd_Preferences.PrintPitch == FINE) {
                        outputBuffer[CPI] = '5';
                }
                if (PD->pd_Preferences.PrintQuality == LETTER) {
                        outputBuffer[QUALITY] = '1';
                }
                /* Change to Landscape (Vert)) if selected) */
                if (PD->pd_Preferences.PrintAspect == ASPECT_VERT) {
                            outputBuffer[ASPECT] = '1';
                }

                j = x; /* set the formlength = textlength, top margin = 1 */
                papersize = PD->pd_Preferences.PaperSize;
		switch (papersize) 
		{
		   case US_LETTER:
			papersize = 10 * lpi;
			break;
		   case US_LEGAL:
			papersize = 13 * lpi;
			break;
		   case EURO_A4:
			papersize = (lpi == 8 ? 85 : 65);
			break;
		   default:   /* Custom size */
			papersize = PD->pd_Preferences.PaperLength;
		}
                textlength = papersize;
                topmargin = 1;

                while (y < FORM_LEN) {
                        outputBuffer[x++] = initForm[y++];
                }
                numberString(textlength, j + LPP, outputBuffer);

                Parms[0] = PD->pd_Preferences.PrintLeftMargin;
                Parms[1] = PD->pd_Preferences.PrintRightMargin;
                *command = aSLRM;
        }

        if (*command == aSLRM) {        /* L&R Margins */
                j = x;
                y = 0;
                while(y < MARG_LEN) {
                        outputBuffer[x++] = initMarg[y++];
                }
                numberString(Parms[0] - 1, j + LEFT_MARG, outputBuffer);
                numberString(Parms[1] - 1, j + RIGHT_MARG, outputBuffer);
                return(x);
        }

        if ((*command == aSUS2) && (*vline == 0)) { /* Superscript on */
                *command = aPLU; /* Partial line up */
                *vline = 1;
                return(0);
        }

        if ((*command == aSUS2) && (*vline < 0)) {
                *command = aRI; /* Reverse LF */
                *vline = 1;
                return(0);
        }

        if ((*command == aSUS1) && (*vline > 0)) {  /* Superscript off */
                *command = aPLD; /* Partial line down */
                *vline = 0;
                return(0);
        }

        if ((*command == aSUS4) && (*vline == 0)) { /* Subscript on */
                *command = aPLD;
                *vline = -1;
                return(0);
        }

        if ((*command == aSUS4) && (*vline > 0)) {
                *command = aIND; /* Line feed */
                *vline = -1;
                return(0);
        }

        if ((*command == aSUS3) && (*vline < 0)) { /* Subscript off */
                *command = aPLU;
                *vline = 0;
                return(0);
        }

        if(*command == aSUS0) {              /* Normalise the line */
                if (*vline > 0) {
                        *command = aPLD;
                }
                if (*vline < 0) {
                        *command = aPLU;
                }
                *vline = 0;
                return(0);
        }

        if (*command == aPLU) {
                (*vline)++;
                return(0);
        }

        if (*command == aPLD){
                (*vline)--;
                return(0);
        }

        if (*command == aSTBM) {        /* Top & bottom margins */
                if (Parms[0] == 0) {
                        Parms[0] = topmargin;
                }
                else {
                        topmargin = --Parms[0];
                }

                if (Parms[1] == 0) {
                        Parms[1] = textlength;
                }
                else {
                        textlength=Parms[1];
                }
                while (x < 13) {
                        outputBuffer[x] = initTMarg[x];
                        x++;
                }
                numberString(Parms[0], 3, outputBuffer);
                numberString(Parms[1] - Parms[0], 10, outputBuffer);
                return(x);
        }

        if (*command == aSLPP) {        /* Set form length */
                while(x < FORM_LEN) {
                        outputBuffer[x] = initForm[x];
                        x++;
                }
                /*restore textlength, margin*/
                numberString(topmargin, 3, outputBuffer);
                numberString(textlength, 10, outputBuffer);
                return(x);
        }

        if (*command == aRIS) {         /* Reset */
                PD->pd_PWaitEnabled = 253;   /* Save data! */
        }

        if (*command == aSFC) {               /* Foreground colour */
                          if (Parms[0] == 39)
                                   Parms[0] = 30;
                          if (Parms[0] > 37)
                                   return(0);
                          outputBuffer[x++] = '\033';
                          outputBuffer[x++] = '*';
                          outputBuffer[x++] = 'v';
                          outputBuffer[x++] = ISOColorTable[Parms[0]-30];
                          if (Parms[0] == 34)
                              outputBuffer[x++] = '2';
                          if (Parms[0] == 35)
                              outputBuffer[x++] = '0';
                          outputBuffer[x++] = 'S';
                          return(x);
        }
        return(0);
}

/* Inserts Param into output buffer */
void numberString(UBYTE Param, int x, char outputBuffer[])
{
        if (Param > 199) {
                outputBuffer[x++] = '2';
                Param -= 200;
        }
        else if (Param > 99) {
                outputBuffer[x++] = '1';
                Param -= 100;
        }
        else {
                outputBuffer[x++] = '0'; /* always return 3 digits */
        }

        if (Param > 9) {
                outputBuffer[x++] = Param / 10 + '0';
        }
        else {
                outputBuffer[x++] = '0';
        }

        outputBuffer[x] = Param % 10 + '0';
}

ConvFunc(char *buf, char c, int flag)
/* expand lf into lf/cr flag (0-yes, else no ) */
{
        if (c == '\014') { /* if formfeed (page eject) */
                PED->ped_PrintMode = 0; /* no data to print */
        }
        return(-1); /* pass all chars back to the printer device */
}

Close(ior)
struct printerIO *ior;
{
        if (PED->ped_PrintMode) { /* if data has been printed */
                (*(PD->pd_PWrite))("\014",1); /* eject page */
                (*(PD->pd_PBothReady))(); /* wait for it to finish */
                PED->ped_PrintMode = 0; /* no data to print */
        }
        return(0);
}

