[Contents] [Index] [Help] [Retrace] [Browse <] [Browse >]

/* Demo_Dump.c
 *
 * Simple example of dumping a rastport to the printer, changing
 * printer preferences programmatically and handling error codes.
 *
 * Compile with SAS C 5.10a. lc -cfist -v -L Demo_Dump
 *
 * Requires Kickstart V37
 * Run from CLI only
 */

#include <exec/types.h>
#include <exec/memory.h>
#include <exec/ports.h>
#include <devices/printer.h>
#include <devices/prtbase.h>
#include <dos/dos.h>
#include <intuition/intuition.h>
#include <intuition/screens.h>
#include <graphics/displayinfo.h>

#include <clib/exec_protos.h>
#include <clib/alib_protos.h>
#include <clib/alib_stdio_protos.h>
#include <clib/graphics_protos.h>
#include <clib/intuition_protos.h>

struct IntuitionBase *IntuitionBase;
struct GfxBase *GfxBase;

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

struct EasyStruct reqES =
{
    sizeof(struct EasyStruct), 0, "DemoDump",
    "%s",
    NULL,
};

/* Possible printer.device and I/O errors */
static UBYTE *ErrorText[] =
{
    "PDERR_NOERR",
    "PDERR_CANCEL",
    "PDERR_NOTGRAPHICS",
    "INVERTHAM",                /* OBSOLETE */
    "BADDIMENSION",
    "DIMENSIONOVFLOW",  /* OBSOLETE */
    "INTERNALMEMORY",
    "BUFFERMEMORY",
    /* IO_ERRs */
    "IOERR_OPENFAIL",
    "IOERR_ABORTED",
    "IOERR_NOCMD",
    "IOERR_BADLENGTH"
};

/* Requester Action text */
static UBYTE *ActionText[] =
{
    "OK|CANCEL",
    "Continue",
    "Abort",
};

#define OKCANCELTEXT 0
#define CONTINUETEXT 1
#define ABORTTEXT    2

VOID main(VOID);

VOID main(VOID)
{
struct MsgPort  *PrinterMP;
union printerIO *PIO;
struct PrinterData *PD;
struct PrinterExtendedData *PED;
struct Screen *pubscreen;
struct ViewPort *vp;
STRPTR textbuffer;
LONG modeID, i,j;
ULONG dcol[5], drow[5];
ULONG signal;

/* Fails silently if not V37 or greater. Nice thing to do would be to put up
 * a V33 requester of course.
 */

/* Set up once */
reqES.es_GadgetFormat = ActionText[CONTINUETEXT];

if (IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library", 37))
  {
  /* Using graphics.library to get the displaymodeID of the public screen,
   * which we'll pass to the printer.device.
   */
  if (GfxBase = (struct GfxBase *)OpenLibrary("graphics.library", 37))
    {
    if (textbuffer = (STRPTR)AllocMem(256, MEMF_CLEAR))
      {
      /* Create non-public messageport. Since we depend on V37 already, we'll
       * use the new Exec function.
       */
      if (PrinterMP = CreateMsgPort())
        {
        /* Allocate printerIO union */
        if (PIO = (union printerIO *)CreateExtIO(PrinterMP, sizeof(union printerIO)))
          {
          /* Open the printer.device */
          if (!(OpenDevice("printer.device",0,(struct IORequest *)PIO,0)))
            {
            /* Yahoo, we've got it.
             * We'll use the PrinterData structure to get to the the printer
             * preferences later on. The PrinterExtendedData structure will
             * reflect the changes we'll make to the preferences.
             */

            PD = (struct PrinterData *)PIO->iodrp.io_Device;
            PED = (struct PrinterExtendedData *)&PD->pd_SegmentData->ps_PED;

            /* We're all set. We'll grab the default public screen (normally
             * Workbench) and see what happens when we dump it with different
             * densities.
             * Next we'll put up a nice requester for the user and ask if
             * (s)he wants to actually do the dump.
             */

            if (pubscreen = LockPubScreen(NULL))
              {
              vp = &(pubscreen->ViewPort);
              /* Use graphics.library/GetVPModeID() to get the ModeID of the screen. */
              if ((modeID = GetVPModeID(vp)) != INVALID_ID)
                {
                /* Seems we got a valid ModeID for the default public screen (surprise).
                 * Do some fake screen dumps with densities 1, 3, 5 and 7. Depending on
                 * the driver, one or more may be the same.
                 */

                /* Fill in those parts of the IODRPRequest which won't change */
                PIO->iodrp.io_Command = PRD_DUMPRPORT;
                PIO->iodrp.io_RastPort = &(pubscreen->RastPort);
                PIO->iodrp.io_ColorMap = vp->ColorMap;
                PIO->iodrp.io_Modes = modeID;
                PIO->iodrp.io_SrcX = pubscreen->LeftEdge;
                PIO->iodrp.io_SrcY = pubscreen->TopEdge;
                PIO->iodrp.io_SrcWidth = pubscreen->Width;
                PIO->iodrp.io_SrcHeight = pubscreen->Height;

                for (i = 1,j=0; i < 8; i+=2,j++)
                  {
                  /* On return these will contain the actual dump dimension */
                  PIO->iodrp.io_DestCols = 0;
                  PIO->iodrp.io_DestRows = 0;
                  /* We'll simply change our local copy of the
                   * Preferences structure. Likewise we could change
                   * all printer-related preferences.
                   */
                  PD->pd_Preferences.PrintDensity = i;
                  PIO->iodrp.io_Special = SPECIAL_NOPRINT|SPECIAL_ASPECT;

                  /* No need to do asynchronous I/O here */
                  DoIO((struct IORequest *)PIO);

                  if (PIO->iodrp.io_Error == 0)
                    {
                    dcol[j] = PIO->iodrp.io_DestCols;
                    drow[j] = PIO->iodrp.io_DestRows;
                    }
                  else
                    {
                    j = PIO->iodrp.io_Error;
                    if (j < 0)
                      j = j * -1 + 7;

                    sprintf(textbuffer, "Error: %s\n", ErrorText[j]);
                    reqES.es_GadgetFormat = ActionText[CONTINUETEXT];
                    EasyRequest(NULL, &reqES, NULL, textbuffer);
                    break;
                    }
                  }
                /* Simple, lazy way to check if we encountered any problems */
                if (i == 9)
                  {
                  /* Build an 'intelligent' requester */
                  sprintf(textbuffer,
                    "%s: %5ld x %5ld\n%s: %5ld x %5ld\n%s: %5ld x%5ld\n%s: %5ld x %5ld\n\n%s",
                    "Density 1", dcol[0], drow[0],
                    "Density 3", dcol[1], drow[1],
                    "Density 5", dcol[2], drow[2],
                    "Density 7", dcol[3], drow[3],
                    "Print screen at highest density?");
                  reqES.es_GadgetFormat = ActionText[OKCANCELTEXT];

                  /* Obviously the choice presented to the user here is a very
                   * simple one. To print or not to print. In a real life
                   * application, a requester could be presented, inviting
                   * the user to select density, aspect, dithering etc.
                   * The fun part is, of course, that the user can, to a certain
                   * degree, be informed about the effects of her/his selections.
                   */
                  if (EasyRequest(NULL, &reqES, NULL, textbuffer))
                    {
                    /* We've still got the density preference set to the highest
                     * density, so no need to change that.
                     * All we do here is re-initialize io_DestCols/Rows and remove
                     * the SPECIAL_NOPRINT flag from io_Special.
                     */
                    PIO->iodrp.io_DestCols = 0;
                    PIO->iodrp.io_DestRows = 0;
                    PIO->iodrp.io_Special &= ~SPECIAL_NOPRINT;

                    /* Always give the user a change to abort.
                     * So we'll use SendIO(), instead of DoIO(), to be asynch and
                     * catch a possible user request to abort printing. Normally,
                     * the user would be presented with a nice, fat, ABORT requester.
                     * However, since this example doesn't even open a window, and is
                     * basically a 'GraphicDumpDefaultPubscreen' equivalent, we'll use
                     * CTRL-C as the user-abort. Besides that, got to keep it short.
                     */
                    SendIO((struct IORequest *)PIO);

                    /* Now Wait() for either a user signal (CTRL-C) or a signal from
                     * the printer.device
                     */
                    signal = Wait(1 << PrinterMP->mp_SigBit | SIGBREAKF_CTRL_C);

                    if (signal & SIGBREAKF_CTRL_C)
                      {
                      /* User wants to abort */
                      AbortIO((struct IORequest *)PIO);
                      WaitIO((struct IORequest *)PIO);
                      }

                    if (signal & (1 << PrinterMP->mp_SigBit))
                      {
                      /* printer is either ready or an error has occurred */
                      /* Remove any messages */
                      while(GetMsg(PrinterMP));
                      }
                    /* Check for errors (in this case we count user-abort as an error) */
                    if (PIO->iodrp.io_Error != 0)
                      {
                      j = PIO->iodrp.io_Error;
                      if (j < 0)
                        j = j * -1 + 7;
                      sprintf(textbuffer, "Error: %s\n", ErrorText[j]);
                      reqES.es_GadgetFormat = ActionText[CONTINUETEXT];
                      EasyRequest(NULL, &reqES, NULL, textbuffer);
                      }

                    } /* else user doesn't want to print */
                  }
                }
              else
                /* Say what? */
                EasyRequest(NULL, &reqES, NULL, "Invalid ModeID\n");
              UnlockPubScreen(NULL, pubscreen);
              }
            else
              EasyRequest(NULL, &reqES, NULL, "Can't lock Public Screen\n");

            CloseDevice((struct IORequest *)PIO);
            }
          else
            EasyRequest(NULL, &reqES, NULL, "Can't open printer.device\n");

          DeleteExtIO((struct IORequest *)PIO);
          }
        else
          EasyRequest(NULL, &reqES, NULL, "Can't create Extented I/O Request\n");
        DeleteMsgPort(PrinterMP);
        }
      else
        EasyRequest(NULL, &reqES, NULL, "Can't create Message port\n");
      /* else Out of memory? 256 BYTES? */
      FreeMem(textbuffer,256);
      }
    CloseLibrary(GfxBase);
    } /* else MAJOR confusion */
  CloseLibrary(IntuitionBase);
  }
}