#include "graph.h"
#include <devices/prtbase.h>

#define WWW (xoffset+maxx+FUDGE)
#define HHH (yoffset+maxy+FUDGE)

extern void *pd_ior0;

static int success;

union printerIO *CreatePrtReq(void);
void DeletePrtReq(union printerIO *);
int OpenPrinter (union printerIO *);
void ClosePrinter(union printerIO *);
void DumpRPort(union printerIO *request, struct RastPort *rastPort, struct ColorMap *colorMap,
          ULONG modes, UWORD sx, WORD sy, WORD sw, WORD sh,
          LONG dc, LONG dr, UWORD s);

void cleanexit(char *);

union printerIO {
    struct IOStdReq    ios;
    struct IODRPReq    iodrp;
    struct IOPrtCmdReq iopc;
};

static char *prtErrorText[] = {" EVERYTHING'S FINE", 
                               " USER CANCELED DUMP", 
                               " NOT A GRAPHICS PRINTER",
                               " SHOULDN'T GET THIS ONE",
                               " ILLEGAL DIMENSIONS", 
                               " SHOULDN'T GET THIS ONE", 
                               " NO MEMORY FOR VARIABLES", 
                               " NO MEMORY FOR BUFFER"};

union printerIO *printerReq;
BOOL PDOPEN = FALSE;


int PrintGraph(int extraflags)
{
    struct IntuiMessage *msg;
    struct MsgPort *port;

    ULONG usersig, printersig, signal;
    BOOL P_ABORT = FALSE;
    BOOL U_ABORT = FALSE;
    int Modes = 0; /* ???? */
    struct ColorMap *colormap;

    int destwidth, destheight;

    success = 1;

    if (!(printerReq = CreatePrtReq())) {
        cleanexit("Can't create printer request");
        return success;
    }

    if (OpenPrinter(printerReq)) {
        cleanexit("Can't open printer device\n");
        return success;
    }

    PDOPEN = TRUE;

    port = printerReq->ios.io_Message.mn_ReplyPort;

    usersig    = 1 << wG->UserPort->mp_SigBit;
    printersig = 1 << port        ->mp_SigBit;

    colormap = GetColorMap(1<<DEPTH);

    SetRGB4CM(colormap, 0, 0xFF,0xFF,0xFF); /* 0 is white */
    SetRGB4CM(colormap, 1, 0   ,0   ,0   ); /* 1 is black */

    destwidth  = WWW;
    destheight = HHH;

    DumpRPort(printerReq, rast, colormap, Modes,
              0, 0,
              WWW, HHH,
              destwidth, destheight,
                extraflags
           /* | SPECIAL_TRUSTME */
              | SPECIAL_CENTER       /* only centers in narrow direction */
              );

    FOREVER {
        signal = Wait(usersig | printersig);
        if (signal & usersig){ 
            while(msg = (struct IntuiMessage *)GetMsg(wG->UserPort)) {
                if (   (msg->Class == GADGETUP)
                    || (msg->Class == GADGETDOWN)) {
                    if (msg->IAddress == (APTR)&go) {
                        U_ABORT = TRUE;
                    }
                }
                ReplyMsg((struct Message *)msg);
            }
        }
        if (signal & printersig) {
            if (printerReq->iodrp.io_Error != 0) {
                P_ABORT = TRUE;
                while(msg = (struct IntuiMessage *)GetMsg(port)) {
                    /* ReplyMsg((struct Message *)msg); /* ??? */
                }
            } else {
                /* printer done */
                while(msg = (struct IntuiMessage *)GetMsg(port)) {
                    /* ReplyMsg((struct Message *)msg); /* ??? */
                }
                cleanexit("");
                return success;
            }
        }
        if (P_ABORT) {
            quit(NULL);
            cleanexit("Printer problem");
            return 0;
        }
        if (U_ABORT) {
            AbortIO((struct IORequest *)printerReq);
            WaitIO((struct IORequest *)printerReq);
            cleanexit("User aborted.  Your printer's probably hosed.");
            return 0;
        }
    }
}

void cleanexit(char *s)
{
    static int orig_cols,  orig_rows;
    static int final_cols, final_rows;

#if 0
/* try some prefs stuff */
    printf(
      "((struct PrinterData *)(printerReq->iodrp.io_Device))->pd_Preferences->PrintMaxWidth = %d\n",
       ((struct PrinterData *)(printerReq->iodrp.io_Device))->pd_Preferences->PrintMaxWidth);
    printf(
      "(struct PrinterData *)(printerReq->iodrp.io_Device)->pd_Preferences->PrintMaxHeight = %d\n",
       (struct PrinterData *)(printerReq->iodrp.io_Device)->pd_Preferences->PrintMaxHeight);
    printf(
      "(struct PrinterData *)(printerReq->iodrp.io_Device)->pd_Preferences->FontHeight = %d\n",
       (struct PrinterData *)(printerReq->iodrp.io_Device)->pd_Preferences->FontHeight);
    printf(
      "(struct PrinterData *)(printerReq->iodrp.io_Device)->pd_Preferences->PrintDensity = %d\n",
       (struct PrinterData *)(printerReq->iodrp.io_Device)->pd_Preferences->PrintDensity);
#endif

    orig_cols  = WWW; /* for debugging */
    orig_rows  = HHH;
    final_cols = printerReq->iodrp.io_DestCols;
    final_rows = printerReq->iodrp.io_DestRows;

    if (*s) {
        sprintf(messagebuf, "Aborting: %s", s);
        message(messagebuf);
    }
    if (PDOPEN) {
        CloseDevice((struct IORequest *)printerReq);
    }
    if (printerReq) {
        if (   (printerReq->iodrp.io_DestCols < HHH)
            || (printerReq->iodrp.io_DestRows < WWW) ) {
            success = 0;
	    message("Done.");
#if 0
            printf("Original cols, rows: %d, %d (%.2f x %.2f inches)\n",
                   WWW, HHH,
                   WWW/(float)x_dpi_V,
                   HHH/(float)y_dpi_V);
            printf("Final    cols, rows: %d, %d (%.2f x %.2f inches)\n",
                   printerReq->iodrp.io_DestCols,
                   printerReq->iodrp.io_DestRows,
                   printerReq->iodrp.io_DestCols/(float)x_dpi_V,
                   printerReq->iodrp.io_DestRows/(float)y_dpi_V);
#endif
        }
        DeletePrtReq(printerReq);
    }
}


/* the printer i/o routines we use */

union printerIO *CreatePrtReq()
{
    struct MsgPort *prtport;
    union printerIO *request;

    if (!(prtport = CreatePort(NULL,0)))
        return(0);
    if (!(request = (union printerIO *)CreateExtIO(prtport, 
                        sizeof(union printerIO)))){
        DeletePort(prtport);
        return(0);
    }
    return(request);
}

void DeletePrtReq(request)
union printerIO *request;
{
    struct MsgPort *prtport;

    prtport = request->ios.io_Message.mn_ReplyPort;
    DeleteExtIO((struct IORequest *)request);
    DeletePort(prtport);
}
    
int
OpenPrinter(request)
union printerIO *request;
{
        return(
        (int)OpenDevice(
        (UBYTE *)"printer.device",
        0,
        (struct IORequest *)request,
        0));
}

void
DumpRPort(union printerIO *request,
          struct RastPort *rastPort,
          struct ColorMap *colorMap,
          ULONG modes,
          UWORD sx, WORD sy, WORD sw, WORD sh,
          LONG dc, LONG dr,
          UWORD s)
{
    request->iodrp.io_Command = PRD_DUMPRPORT;
    request->iodrp.io_RastPort = rastPort;
    request->iodrp.io_ColorMap = colorMap;
    request->iodrp.io_Modes = modes;
    request->iodrp.io_SrcX = sx;
    request->iodrp.io_SrcY = sy;
    request->iodrp.io_SrcWidth = sw;
    request->iodrp.io_SrcHeight = sh;
    request->iodrp.io_DestCols = dc;
    request->iodrp.io_DestRows = dr;
    request->iodrp.io_Special = s;
    SendIO((struct IORequest *)request);
}
