[comp.sources.amiga] v89i118: dps - display printscript image

page%swap@Sun.COM (Bob Page) (05/09/89)

Submitted-by: allen%hpfcacn@hp-sde.sde.hp.com (Allen Norskog)
Posting-number: Volume 89, Issue 118
Archive-name: util/dps.1

DPS is a program that allows you to display on the screen an image
that is generated by PrintScript, which is a PostScript interpreter
for the Amiga.  PrintScript is a commercial program from Pixeletions.

# This is a shell archive.
# Remove anything above and including the cut line.
# Then run the rest of the file through 'sh'.
# Unpacked files will be owned by you and have default permissions.
#----cut here-----cut here-----cut here-----cut here----#
#!/bin/sh
# shar: SHell ARchive
# Run the following text through 'sh' to create:
#	dps.c
#	dps.doc
# This is archive 1 of a 1-part kit.
# This archive created: Mon May  8 12:14:35 1989
echo "extracting dps.c"
sed 's/^X//' << \SHAR_EOF > dps.c
X/*  DPS  V1.1
X
XAuthor: Allen Norskog
X
XRevision history:
X    V1.0:   3/28/89 - (unofficial release) 
X    V1.1:   4/23/89 - First real release 
X                    - bug fixes to V1.0
X                    - Allow Workbench startup
X
XThis program released into the Public Domain.
X
XThis program compiled with Manx Aztec C V3.6A using
X32 bit integers.  (cc +L;  ln ... -lc32) */
X
X#include <stdio.h>
X#include <exec/memory.h>
X#include <intuition/intuition.h>
X#include <intuition/screens.h>
X#include <graphics/display.h>
X#include <graphics/gfxmacros.h>
X#include <workbench/startup.h>
X#include <workbench/workbench.h>
X#include <workbench/icon.h>
X#include <functions.h>
X
XFILE *fopen(),*ifile=NULL;
X
X
X#define ARG_REQ_NUM     1
X#define ARG_INFILE      1
X
X#define ERR_NUM_ARGS    1
X#define ERR_INFILE      2
X#define ERR_BAD_HEADER  3
X#define ERR_G_LIB       4
X#define ERR_INT_LIB     5
X#define ERR_P_WINDOW    6
X#define ERR_ABORT       7
X#define ERR_NO_IMAGE    8
X#define ERR_SCREEN      9
X#define ERR_S_WINDOW    10
X#define ERR_SHORT_FILE      11
X#define ERR_HEADER_VERSION  12
X#define ERR_HEADER_FLAGS    13
X
X
X
X#define MP_S_WINDOW     0
X#define MP_QUIT         1
X
X/* 8.5 * 72 = 612;  11 * 72 =792 */
X#define DEF_DOTS_WIDE       612
X#define DEF_DOTS_TALL       792
X#define DEF_HALF_DOTS_TALL  396
X
X/* 612 / 16 ~= 39 */
X#define DEF_LINE_WORDS          39
X#define DEF_SMALL_LINE_WORDS    20
X#define DEF_LINE_BYTES          78
X/* For now, things are rather customized to 640 by 400 screen */
X#define DEF_SCREEN_HEIGHT       400
X#define TWO_E16                 65536
X#define TWO_E16_MINUS_1         65535
X#define IMAGESIZE               DEF_LINE_WORDS*DEF_DOTS_TALL
X#define SMALL_IMAGESIZE         DEF_SMALL_LINE_WORDS*DEF_HALF_DOTS_TALL
X#define NORMALFLAGS     (WINDOWSIZING|WINDOWDRAG|WINDOWCLOSE|WINDOWDEPTH)
X
Xextern struct WBStartup *WBenchMsg;
X
Xstatic char *err_msg[]=
X{
X"Everything ok.\n",
X"Command format:  dps infile\n\n\
X   Command displays a PrintScript run length encoded file.\n\n",
X"Input file does not exist.\n\n",
X"This is not a proper PrintScript file.\n\n",
X"Graphics library won't open!\n\n",
X"Intuition library won't open!\n\n",
X"Unable to open page display window!  Probably low on memory.\n\n",
X"Dps aborted.\n\n",
X"Unable to create image!  Probably low on memory.\n\n",
X"Unable to open custom screen!  Probably low on memory.\n\n",
X"Unable to open overview window!  Probably low on memory.\n\n",
X"File too short for even header.\n\n",
X"Version number in file header must be 1.\n\n",
X"Flags number in file header must be 1 (RLE).\n\n"
X};
X
Xint     version;
Xint     flags;
Xint     xdpi;
Xint     ydpi;
Xint     width;
Xint     height;
X
Xint     from_wb=FALSE;
Xint     bytes_per_line;
Xint     max_bytes_out;
Xint     bytes_out=0;
Xint     field_length;
Xint     field_count=0;
Xint     repeat_count=0;
Xint     data_byte=0;
Xint     nibble=0;
Xint     blank_line=TRUE;
Xint     new_line[DEF_LINE_BYTES];
Xint     page_line_count=0;
Xint     screen_lines=DEF_SCREEN_HEIGHT;
Xchar    *con_name = "CON:20/20/600/40/ DPS  V1.1";
XUSHORT  *image=NULL;
XUSHORT  *small_image=NULL;
XUSHORT  color_map[]={
X0x0867, /* Gray page background to reduce flicker */
X0x0000, /* Black text on paper */
X0x0404, /* Dark purple */
X0x0640  /* Yellow */
X};
X
Xstruct  Image   small_page = {
X    0, 0,       /* LeftEdge, TopEdge */
X    DEF_LINE_WORDS*8, DEF_HALF_DOTS_TALL,   /* Width, Height */
X    1,          /* Depth */
X    NULL,       /* *ImageData */
X    1, 0,       /* PlanePick, PlaneOnOff */
X    NULL        /* *NextImage */
X};
X
Xstruct  Image   page = {
X    -10, 0,     /* LeftEdge, TopEdge */
X    DEF_LINE_WORDS*16, DEF_DOTS_TALL,   /* Width, Height */
X    1,          /* Depth */
X    NULL,       /* *ImageData */
X    1, 0,       /* PlanePick, PlaneOnOff */
X    NULL        /* *NextImage */
X};
X
Xstruct  Border  slide_border1 = {
X    0, 0,           /* LeftEdge, TopEdge */
X    1, 2, JAM1,     /* FrontPen, BackPen (ignored), DrawMode */
X    0,              /* Count */
X    NULL,       /* *XY */
X    NULL            /* *NextBorder */
X};
X
Xstruct  Border  slide_border2 = {
X    0, 0,           /* LeftEdge, TopEdge */
X    1, 2, JAM1,     /* FrontPen, BackPen (ignored), DrawMode */
X    0,              /* Count */
X    NULL,       /* *XY */
X    NULL            /* *NextBorder */
X};
X
Xstruct  PropInfo    prop_slider1 = {
X    FREEVERT | AUTOKNOB,        /* Flags */
X    0,                          /* HorizPot */
X    0,                          /* VertPot */
X    0xFFFF,                     /* HorizBody */
X    0x5555,                     /* VertBody */
X    0,                          /* CWidth */
X    0,                          /* CHeight */
X    0,                          /* HPotRes */
X    0,                          /* VPotRes */
X    0,                          /* LeftBorder */
X    0                           /* TopBorder */
X};
X
Xstruct  PropInfo    prop_slider2 = {
X    FREEVERT | AUTOKNOB,        /* Flags */
X    0,                          /* HorizPot */
X    0,                          /* VertPot */
X    0xFFFF,                     /* HorizBody */
X    0x5555,                     /* VertBody */
X    0,                          /* CWidth */
X    0,                          /* CHeight */
X    0,                          /* HPotRes */
X    0,                          /* VPotRes */
X    0,                          /* LeftBorder */
X    0                           /* TopBorder */
X};
X
Xstruct  Gadget  slider1 = {
X    NULL,                       /* *NextGadget */
X    -18, 12, 16, -25,           /* LeftEdge, TopEdge, 
X                                    Width, Height */
X    GADGHCOMP | GRELRIGHT | GRELHEIGHT,     /* Flags */
X    GADGIMMEDIATE|FOLLOWMOUSE|RELVERIFY,    /* Activation */
X    PROPGADGET | GZZGADGET,     /* GadgetType */
X    (APTR)&slide_border1,       /* GadgetRender */
X    NULL,                       /* SelectRender */
X    NULL,                       /* *GadgetText */
X    0,                          /* MutualExclude */
X    (APTR)&prop_slider1,            /* SpecialInfo */
X    1,                          /* GadgetID */
X    NULL                        /* UserData */
X};
X
Xstruct  Gadget  slider2 = {
X    NULL,                       /* *NextGadget */
X    -18, 12, 16, -25,           /* LeftEdge, TopEdge, 
X                                    Width, Height */
X    GADGHCOMP | GRELRIGHT | GRELHEIGHT,     /* Flags */
X    GADGIMMEDIATE|FOLLOWMOUSE|RELVERIFY,    /* Activation */
X    PROPGADGET | GZZGADGET,     /* GadgetType */
X    (APTR)&slide_border2,       /* GadgetRender */
X    NULL,                       /* SelectRender */
X    NULL,                       /* *GadgetText */
X    0,                          /* MutualExclude */
X    (APTR)&prop_slider2,            /* SpecialInfo */
X    1,                          /* GadgetID */
X    NULL                        /* UserData */
X};
X
Xstruct IntuiText req_text = {
X    0,1,                        /* FrontPen, BackPen */
X    JAM1,                       /* DrawMode */
X    5,4,                        /* LeftEdge, TopEdge */
X    NULL,                       /* TextAttr */
X    NULL,                       /* UBYTE *IText */
X    NULL                        /* NextText */
X};
X
Xstruct IntuiText cont_text = {
X    0,1,                        /* FrontPen, BackPen */
X    JAM1,                       /* DrawMode */
X    5,4,                        /* LeftEdge, TopEdge */
X    NULL,                       /* TextAttr */
X    (unsigned char *)"Continue",/* UBYTE *IText */
X    NULL                        /* NextText */
X};
X
Xstruct IntuiText p_menu_1_text = {
X    0,1,                        /* FrontPen, BackPen */
X    JAM1,                       /* DrawMode */
X    0,0,                        /* LeftEdge, TopEdge */
X    NULL,                       /* TextAttr */
X    (unsigned char *)"Overview",/* UBYTE *IText */
X    NULL                        /* NextText */
X};
X
Xstruct IntuiText p_menu_2_text = {
X    0,1,                        /* FrontPen, BackPen */
X    JAM1,                       /* DrawMode */
X    0,0,                        /* LeftEdge, TopEdge */
X    NULL,                       /* TextAttr */
X    (unsigned char *)"Quit",    /* UBYTE *IText */
X    NULL                        /* NextText */
X};
X
Xstruct MenuItem p_menu_2 = {
X    NULL,                       /* *NextItem */
X    0,12,80,12,                 /* LeftEdge, TopEdge, Width, Height */
X    ITEMTEXT | HIGHCOMP | ITEMENABLED,      /* Flags */
X    0,                          /* MutualExclude */
X    (APTR)&p_menu_2_text,       /* ItemFill */
X    0,                          /* Command */
X    NULL,                       /* *SubItem */
X    0                           /* NextSelect */
X};
X
Xstruct MenuItem p_menu_1 = {
X    &p_menu_2,                  /* *NextItem */
X    0,0,80,12,                  /* LeftEdge, TopEdge, Width, Height */
X    ITEMTEXT | HIGHCOMP | ITEMENABLED,      /* Flags */
X    0,                          /* MutualExclude */
X    (APTR)&p_menu_1_text,       /* ItemFill */
X    0,                          /* Command */
X    NULL,                       /* *SubItem */
X    0                           /* NextSelect */
X};
X
Xstruct Menu project_menu = {
X    NULL,                       /* *NextMenu */
X    0,0,80,12,                  /* LeftEdge, TopEdge, Width, Height */
X    MENUENABLED,                /* Flags */
X    (BYTE *)"Project",          /* BYTE *MenuName */
X    &p_menu_1                   /* *FirstItem */
X};
X
Xstatic struct NewScreen myDpsScreen = {
X    0, 0,                   /* SHORT LeftEdge, TopEdge */
X    640, DEF_SCREEN_HEIGHT, /* Width, Height */
X    2,                      /* Depth */
X    0, 1,                   /* UBYTE DetailPen, BlockPen */
X    HIRES | INTERLACE,      /* USHORT ViewModes */
X    CUSTOMSCREEN,           /* USHORT Type */
X    NULL,                   /* struct TextAttr *Font */
X    (unsigned char *)"DPS Screen", /* UBYTE *DefaultTitle */
X    NULL,                   /* struct Gadget *Gadgets */
X    NULL                    /* struct BitMap *CustomBitMap */
X};
X
Xstatic struct NewWindow myPageWindow = {
X    0, 0,                   /* SHORT LeftEdge, TopEdge */
X    640,                    /* Width */
X    DEF_SCREEN_HEIGHT,      /* Height */
X    -1, -1,                 /* UBYTE DetailPen, BlockPen */
X                            /* ULONG IDCMPFlags */
X    CLOSEWINDOW | NEWSIZE | MENUPICK | GADGETDOWN | GADGETUP | MOUSEMOVE,
X                            /* ULONG Flags */
X    SMART_REFRESH|NOCAREREFRESH|NORMALFLAGS|GIMMEZEROZERO,
X    &slider1,               /* struct Gadget *FirstGadget */
X    NULL,                   /* struct Image *CheckMark */
X    (unsigned char *)"DPS  V1.1", /* UBYTE *Title */
X    NULL,                   /* struct Screen *Screen */
X    NULL,                   /* struct BitMap *BitMap */
X    80, 50, 640, 400,       /* SHORT MinWidth,MinHeight, 
X                                     MaxWidth, MaxHeight*/
X    CUSTOMSCREEN            /* USHORT Type */
X};
X
Xstatic struct NewWindow mySmallWindow = {
X    0, 0,                   /* SHORT LeftEdge, TopEdge */
X    DEF_LINE_WORDS*8+28,    /* Width */
X    DEF_SCREEN_HEIGHT,      /* Height */
X    -1, -1,                 /* UBYTE DetailPen, BlockPen */
X                            /* ULONG IDCMPFlags */
X    CLOSEWINDOW | NEWSIZE | MENUPICK | GADGETDOWN | GADGETUP | MOUSEMOVE,
X                            /* ULONG Flags */
X    SMART_REFRESH|NOCAREREFRESH|NORMALFLAGS|GIMMEZEROZERO,
X    &slider2,               /* struct Gadget *FirstGadget */
X    NULL,                   /* struct Image *CheckMark */
X    (unsigned char *)"Overview", /* UBYTE *Title */
X    NULL,                   /* struct Screen *Screen */
X    NULL,                   /* struct BitMap *BitMap */
X    80, 50, 640, 400,       /* SHORT MinWidth,MinHeight, 
X                                     MaxWidth, MaxHeight*/
X    CUSTOMSCREEN            /* USHORT Type */
X};
X
Xstruct  Screen      *dpsScreen=NULL;
Xstruct  Window      *pageWindow=NULL;
Xstruct  Menu        *pageWindowMenu=NULL;
Xstruct  Window      *smallWindow=NULL;
Xstruct  RastPort    *Rport1=NULL;
Xstruct  RastPort    *Rport2=NULL;
Xstruct  Library     *IconBase=NULL;
Xstruct  Library     *GfxBase=NULL;
Xstruct  Library     *IntuitionBase=NULL;
X
X
Xvoid disp_err(x)
X    int x;
X{
X    struct FileHandle *con;
X
X    if (from_wb) {
X        if (pageWindow) {
X            req_text.IText = (UBYTE *) err_msg[x];
X            x = AutoRequest(pageWindow,&req_text,NULL,&cont_text,
X                        NULL,NULL,600,60);
X        }
X        else {
X            con = Open(con_name,MODE_OLDFILE);
X            if (con) {
X                Write(con,err_msg[x],strlen(err_msg[x]));
X                Delay(120);
X                Close(con);
X            }
X        }
X    }
X    else {
X        printf(err_msg[x]);
X    }
X}
X
Xvoid err_exit(x)
X    int x;
X{
X    disp_err(x);
X    exit(x); /* err_exit is not called when any windows/screens are open */
X}
X
Xvoid redraw_small_image()
X{
X    int     image_lines;
X    int     first_line;
X    int     last_line;
X
X
X    image_lines = smallWindow->Height - smallWindow->BorderTop -
X                    smallWindow->BorderBottom;
X    last_line = DEF_HALF_DOTS_TALL - image_lines;
X    first_line = (prop_slider2.VertPot * last_line)/ TWO_E16_MINUS_1;
X
X    DrawImage(Rport2,&small_page,0,-first_line);
X}
X
Xvoid redraw_image()     /* redraws large image */
X{
X    int image_lines;
X    int     first_line;
X    int     last_line;
X
X
X    image_lines = pageWindow->Height - pageWindow->BorderTop -
X                    pageWindow->BorderBottom;
X    last_line = DEF_DOTS_TALL - image_lines;
X    first_line = (prop_slider1.VertPot * last_line)/ TWO_E16_MINUS_1;
X
X    DrawImage(Rport1,&page,0,-first_line);
X}
X
Xvoid redraw_small_window() /* sets slider and redraws small image */
X{
X    int     image_lines;
X    int     body;
X    int     first_line;
X    int     last_line;
X
X
X    image_lines = smallWindow->Height - smallWindow->BorderTop -
X                    smallWindow->BorderBottom;
X    body = (TWO_E16_MINUS_1 * image_lines) / DEF_HALF_DOTS_TALL;
X    last_line = DEF_HALF_DOTS_TALL - image_lines;
X    first_line = (prop_slider2.VertPot * last_line)/ TWO_E16_MINUS_1;
X
X    DrawImage(Rport2,&small_page,0,-first_line);
X    ModifyProp(&slider2,smallWindow,NULL,prop_slider2.Flags,
X        prop_slider2.HorizPot,prop_slider2.VertPot,prop_slider2.HorizBody,
X        body);
X    RefreshGadgets(&slider2,smallWindow,NULL);
X}
X
Xvoid redraw()   /* sets slider and redraws large image */
X{
X    int     image_lines;
X    int     body;
X    int     first_line;
X    int     last_line;
X
X
X    image_lines = pageWindow->Height - pageWindow->BorderTop -
X                    pageWindow->BorderBottom;
X    body = (TWO_E16_MINUS_1 * image_lines) / DEF_DOTS_TALL;
X    last_line = DEF_DOTS_TALL - image_lines;
X    first_line = (prop_slider1.VertPot * last_line)/ TWO_E16_MINUS_1;
X
X    DrawImage(Rport1,&page,0,-first_line);
X    ModifyProp(&slider1,pageWindow,NULL,prop_slider1.Flags,
X        prop_slider1.HorizPot,prop_slider1.VertPot,prop_slider1.HorizBody,
X        body);
X    RefreshGadgets(&slider1,pageWindow,NULL);
X}
X
Xvoid kill_small_window()
X{
X    if (small_image != NULL) {
X        FreeMem(small_image, SMALL_IMAGESIZE*sizeof(USHORT));
X        small_image = NULL;
X    }
X    if (smallWindow) {
X        CloseWindow(smallWindow);
X        smallWindow = NULL;
X    }
X    Rport2=NULL;
X}
X
Xvoid open_small_window()
X{
X    int i,j,k;
X    int big_words;
X    int small_words;
X
X    if (smallWindow == NULL) {
X
X        small_image = (USHORT *) AllocMem(SMALL_IMAGESIZE*sizeof(USHORT), 
X                                            MEMF_CHIP|MEMF_CLEAR);
X        if (small_image == NULL) {
X            disp_err(ERR_NO_IMAGE);
X            return;
X        }
X        small_page.ImageData = small_image;
X
X        big_words =0;   /* Offset to present row in page image */
X        small_words=0;  /* Offset to present row in small image */
X
X        /* The following loop compresses the image 2x in both
X            height and width */
X
X        for (i = 0; i<DEF_HALF_DOTS_TALL; i++) {
X            for (j = 0, k=0; j<DEF_SMALL_LINE_WORDS-1; j++, k += 2) {
X                small_image[small_words+j] = 
X                    (shrink_word(image[big_words+k])<<8) + 
X                    shrink_word(image[big_words+k+1]);
X                small_image[small_words+j] |= 
X                    (shrink_word(image[big_words+k+DEF_LINE_WORDS])<<8) + 
X                    shrink_word(image[big_words+k+DEF_LINE_WORDS+1]);
X            }
X            small_image[small_words+j] =  (shrink_word(image[big_words+k])
X                    |  shrink_word(image[big_words+k+DEF_LINE_WORDS])) <<8;
X            big_words += 2*DEF_LINE_WORDS;
X            small_words += DEF_SMALL_LINE_WORDS;
X        }
X
X        prop_slider2.VertPot = 0; /* This is needed on second opening of
X                                     this window */
X        smallWindow = OpenWindow(&mySmallWindow);
X        Rport2 = smallWindow->RPort;
X        if (smallWindow == NULL) {
X            kill_small_window();
X            disp_err(ERR_S_WINDOW);
X            return;
X        }
X        redraw_small_window();
X    }
X}
X
Xvoid kill_page_window()
X{
X    if (image) {
X        FreeMem(image, IMAGESIZE*sizeof(USHORT));
X        image = NULL;
X    }
X    if (pageWindow) {
X        if (pageWindowMenu) ClearMenuStrip(pageWindow);
X        pageWindowMenu = NULL;
X        CloseWindow(pageWindow);
X        pageWindow = NULL;
X    }
X}
X
Xvoid kill_dps_screen()
X{
X    kill_small_window();
X    kill_page_window();
X    if (dpsScreen) {
X        CloseScreen(dpsScreen);
X        dpsScreen == NULL;
X    }
X}
X
Xvoid open_page_window()
X{
X    myPageWindow.Screen = dpsScreen;
X    mySmallWindow.Screen = dpsScreen;
X
X    pageWindow = OpenWindow(&myPageWindow);
X    if (pageWindow == NULL) {
X        kill_dps_screen();
X        CloseLibrary(IntuitionBase);
X        CloseLibrary(GfxBase);
X        err_exit(ERR_P_WINDOW);
X    }
X
X    pageWindowMenu = &project_menu;
X    SetMenuStrip(pageWindow, pageWindowMenu);
X    Rport1 = pageWindow->RPort;
X    redraw();
X}
X
Xvoid handle_events()
X{
X    int     mouse_moved;
X    int     remove_small_window;
X    int     make_small_window;
X    int     get_out;
X    struct  IntuiMessage *imsg;
X    long    class;
X    USHORT  code;
X    unsigned long m1, m2, res;
X    short   menu, item;
X
X    m1=1L<<pageWindow->UserPort->mp_SigBit;
X    m2=0;
X    for (;;)  {
X        res = Wait(m1|m2);
X        if (res & m1) {
X            get_out=FALSE;
X            mouse_moved=FALSE;
X            make_small_window=FALSE;
X            while (imsg = (struct IntuiMessage *)GetMsg(pageWindow->UserPort)) {
X                class = imsg->Class;
X                code = imsg->Code;
X                ReplyMsg(imsg);
X                switch(class) {
X                    case CLOSEWINDOW:
X                        get_out=TRUE;
X                        break;
X                    case NEWSIZE:
X                        redraw(); 
X                        break;
X                    case GADGETDOWN:    /* Gadget stuff all the same */
X                    case GADGETUP:
X                    case MOUSEMOVE:
X                        mouse_moved = TRUE;
X                        break;
X                    case MENUPICK:
X                        menu = MENUNUM(code);
X                        item = ITEMNUM(code);
X                        if (menu == 0) {
X                            switch(item) {
X                                case(MP_S_WINDOW):
X                                    make_small_window=TRUE;
X                                    break;
X                                case(MP_QUIT):
X                                    get_out=TRUE;
X                                    break;
X                                default:
X                                    break;
X                            }
X                        }
X                        break;
X                    default:
X                        break;
X                }
X            }
X            if (get_out) return;
X            if (mouse_moved) redraw_image();
X            if (make_small_window) {
X                open_small_window();
X                if (smallWindow) m2=1L<<smallWindow->UserPort->mp_SigBit;
X            }
X        }
X        if (res & m2) {
X            mouse_moved = FALSE;
X            remove_small_window = FALSE;
X            while (imsg = (struct IntuiMessage *)GetMsg(smallWindow->UserPort)) {
X                class = imsg->Class;
X                code = imsg->Code;
X                ReplyMsg(imsg);
X                switch(class) {
X                    case CLOSEWINDOW:
X                        remove_small_window = TRUE;
X                        break;
X                    case NEWSIZE:
X                        redraw_small_window(); 
X                        break;
X                    case GADGETDOWN:    /* Gadget stuff all the same */
X                    case GADGETUP:
X                    case MOUSEMOVE:
X                        mouse_moved = TRUE;
X                        break;
X                    default:
X                        break;
X                }
X            }
X            if (remove_small_window) {
X                kill_small_window();
X                m2 = 0;
X            }
X            else if (mouse_moved) redraw_small_image();
X        }
X    }
X}
X
Xint shrink_byte(c)  /* Compress a byte into a nibble.  
X                        This routine not used at present, 
X                        but might be useful */
X    int c;
X{
X    int nibble;
X
X    nibble = 0;
X    if (c & 3) nibble = 1;
X    if (c & 12) nibble |= 2;
X    if (c & 48) nibble |= 4;
X    if (c & 192) nibble |= 8;
X    return(nibble);
X}
X
Xint shrink_word(c)  /* Compress a 16 bit word into 8 bits */
X    unsigned int c;
X{
X    unsigned int byte;
X
X    byte = 0;
X    if (c & 0x3)    byte = 1;
X    if (c & 0xc)    byte |= 2;
X    if (c & 0x30)   byte |= 4;
X    if (c & 0xc0)   byte |= 8;
X    if (c & 0x300)  byte |= 0x10;
X    if (c & 0xc00)  byte |= 0x20;
X    if (c & 0x3000) byte |= 0x40;
X    if (c & 0xc000) byte |= 0x80;
X    return(byte);
X}
X
Xvoid clear_new_line()
X{
X    int j;
X
X    for (j = 0; j<DEF_LINE_BYTES; j++) {
X        new_line[j] = 0;
X    }
X}
X
Xint flip_byte(c)    /* Reverses the bit order */
X    int c;
X{
X    int b;
X
X    b = ((c & 1) <<7) | ((c & 2) <<5) | ((c & 4) <<3) | ((c & 8) <<1);
X    b |= ((c & 0x80) >>7) | ((c & 0x40) >>5) | ((c & 0x20) >>3) | 
X         ((c & 0x10) >>1);
X    return(b);
X}
X
Xvoid clear_image() /* Sets up large image.  Draws a (8.5 x 11) page 
X                        border into the image. */
X{
X    int i;
X    int j;
X
X    image = (USHORT *) AllocMem(IMAGESIZE*sizeof(USHORT), 
X                                MEMF_CHIP|MEMF_CLEAR);
X    if (image == NULL) {
X        err_exit(ERR_NO_IMAGE);
X    }
X    page.ImageData = image;
X
X    /* Draw a page border */
X    i = (DEF_DOTS_TALL-1) * DEF_LINE_WORDS; /* point to last line */
X    for (j = 1; j<DEF_LINE_WORDS; j++) {
X        image[j] = 0xFFFF;
X        image[i+j] = 0xFFFF;
X    }
X    image[0] = 0x000F; /* 8.5inches * 72dpi = 612 bits 
X                        = 38.25 (16bit words)
X                        Therefore, we need 39 words.
X                        Since the line is flipped, data starts on the
X                        third nibble */
X    image[i] = 0x000F;
X    for (j = 1, i=DEF_LINE_WORDS; 
X        j<DEF_DOTS_TALL-1; j++, i += DEF_LINE_WORDS) {
X
X        image[i] = 0x0008;                  /* Beginning of line */
X        image[i+DEF_LINE_WORDS-1] = 0x0001; /* End of line */
X    }
X}
X
Xvoid enter_new_line()   /* puts a line into the large image */
X{
X    int b;
X    int i;
X    int j;
X    int k;
X
X    page_line_count++;
X    if (page_line_count > DEF_DOTS_TALL) return;
X    if (blank_line != TRUE) {
X        k = (DEF_DOTS_TALL-page_line_count)*DEF_LINE_WORDS;
X        for (b=j= 0; j<DEF_LINE_WORDS; j++, b += 2) {
X            i = (new_line[b]<<8) + new_line[b+1];
X            image[k+j] ^= i; /* XOR so that writes on page edges are
X                                visible */
X        }
X    }
X    blank_line = TRUE;
X}
X
Xvoid read_header()  /* Reads the header of a PrintScript run-length-encoded
X                        file. */
X{
X    int     c;
X    int     i;
X    int     done;
X
X
X    /* Read header and check if ok */
X    done = FALSE;
X    i=0;
X    while (done != TRUE) {
X        c = getc(ifile);
X        if (c == EOF) {
X            done = TRUE;
X            disp_err(ERR_SHORT_FILE);
X            err_exit(ERR_BAD_HEADER);
X        }
X        else {
X            i++;
X            switch (i) {
X                case 1:
X                    version = c*256;
X                    break;
X                case 2:
X                    version += c;
X                    /* This needs to be re-thought if future versions
X                        come along. */
X                    if (version != 1) {
X                        disp_err(ERR_HEADER_VERSION);
X                        err_exit(ERR_BAD_HEADER);
X                    }
X                    break;
X                case 3:
X                    flags = c*256;
X                    break;
X                case 4:
X                    flags += c;
X                    if (flags != 1) {
X                        disp_err(ERR_HEADER_FLAGS);
X                        err_exit(ERR_BAD_HEADER);
X                    }
X                    break;
X                case 5:
X                    xdpi = c*256;
X                    break;
X                case 6:
X                    xdpi += c;
X                    break;
X                case 7:
X                    ydpi = c*256;
X                    break;
X                case 8:
X                    ydpi += c;
X                    break;
X                case 9:
X                    width = c*256;
X                    break;
X                case 10:
X                    width += c;
X                    break;
X                case 11:
X                    height = c*256;
X                    break;
X                case 12:
X                    height += c;
X                    done = TRUE;
X                    break;
X                default:
X                    err_exit(ERR_BAD_HEADER); /* Should never get here */
X                    break;
X            }
X        }
X    }
X
X}
X
Xvoid build_image()  /* This reads the part of the PrintScript
X                        run-length-encoded file and builds the image.
X                        Since the PrintScript image is "upside-down",
X                        we need to put the top line to the bottom, etc.,
X                        and also reverse each line left-to-right. */
X{
X    int     c;
X    int     i;
X    int     j;
X    int     done;
X
X    clear_new_line();
X    blank_line = TRUE;
X    done = FALSE;
X    i=0;
X    while (done != TRUE) {
X        c = getc(ifile);
X        if (c == EOF) {
X            done = TRUE;
X        }
X        else {
X            i++;
X            switch (i) {
X                case 1:
X                    field_length = c*256;
X                    field_count = 0;
X                    bytes_out = 0;
X                    break;
X                case 2:
X                    field_length += c;
X                    if (field_length == 0) {
X                        i = 0;
X                        enter_new_line();   /* enter a blank line */
X                        /* clear_new_line(); */
X                    }
X                    else blank_line = FALSE;
X                    break;
X                case 3:
X                    repeat_count = c + 1;
X                    field_count++;
X                    break;
X                case 4:
X                    i = 2;
X                    data_byte = flip_byte(c); /* Reverse byte left-to-right */
X                    field_count++;
X                    if ((repeat_count + bytes_out) > max_bytes_out) {
X                        repeat_count = max_bytes_out - bytes_out;
X                    }
X                    for (j = 0; j<repeat_count; j++) {
X                        /* Put bytes in "backwards".  We want the first
X                            byte to go way over to the right in 
X                            new_line[77]. */
X                        bytes_out++;
X                        new_line[DEF_LINE_BYTES-bytes_out] = data_byte;
X                    }
X                    if (field_count >= field_length) {
X                        i = 0;
X                        enter_new_line();
X                        clear_new_line();
X                    }
X                    break;
X                default:
X                    err_exit(ERR_BAD_HEADER); /* Should never get here */
X                    break;
X            }
X        }
X    }
X
X}
X
Xvoid get_wb_args(wb_msg)
X    struct WBStartup    *wb_msg;
X{
X    struct WBArg        *wb_arg;
X    struct DiskObject   *diskobj;
X    char                **toolarray;
X    int                 i;
X    char                *s;
X
X    wb_arg = wb_msg->sm_ArgList;
X    if ((IconBase = OpenLibrary("icon.library",0))) {
X        diskobj = (struct DiskObject *) GetDiskObject(wb_arg->wa_Name);
X        if (diskobj) {
X            toolarray = (char **) diskobj->do_ToolTypes;
X            s = (char *) FindToolType(toolarray,"FILE");
X            if (s) {
X                ifile=fopen(s,"r");
X            }
X            FreeDiskObject(diskobj);
X        }
X        CloseLibrary(IconBase);
X    }
X    if (!ifile) {
X        err_exit(ERR_INFILE);
X    }
X}
X
Xmain(argc,argv)
X    int argc;
X    char *argv[];
X{
X    struct ViewPort *vp;
X
X    from_wb = (argc == 0);
X
X    if (from_wb) {
X        get_wb_args(WBenchMsg);
X    }
X    else {
X        if (argc <= ARG_REQ_NUM) {
X            err_exit(ERR_NUM_ARGS);
X        }
X        ifile=fopen(argv[ARG_INFILE],"r");
X        if (!ifile) {
X            err_exit(ERR_INFILE);
X        }
X    }
X
X    max_bytes_out = DEF_LINE_BYTES;
X
X    read_header(); 
X
X    /* Old debug stuff
X    printf("version = %d\n", version);
X    printf("flags   = %d\n", flags);
X    printf("xdpi    = %d\n", xdpi);
X    printf("ydpi    = %d\n", ydpi);
X    printf("width   = %d\n", width);
X    printf("height  = %d\n", height);
X    printf("max_bytes_out  = %d\n", max_bytes_out);
X    */
X
X    clear_image();
X    build_image();
X    close(ifile);
X
X    /* If we haven't aborted by this point, start doing graphics */
X
X    GfxBase = OpenLibrary("graphics.library", 0L);
X    if (GfxBase == NULL) { 
X        if (image != NULL) {
X            FreeMem(image, IMAGESIZE*sizeof(USHORT));
X            image = NULL;
X        }
X        err_exit(ERR_G_LIB); 
X    }
X    IntuitionBase = OpenLibrary("intuition.library", 0L);
X    if (IntuitionBase == NULL) {
X        if (image != NULL) {
X            FreeMem(image, IMAGESIZE*sizeof(USHORT));
X            image = NULL;
X        }
X        CloseLibrary(GfxBase);
X        err_exit(ERR_INT_LIB);
X    }
X
X    dpsScreen = OpenScreen(&myDpsScreen);
X    if (dpsScreen == NULL) {
X        kill_dps_screen();
X        CloseLibrary(IntuitionBase);
X        CloseLibrary(GfxBase);
X        err_exit(ERR_SCREEN);
X    }
X    vp = &dpsScreen->ViewPort;
X    LoadRGB4(vp,color_map,4);
X
X    open_page_window();
X    handle_events();
X
X    kill_dps_screen();
X    if (IntuitionBase) CloseLibrary(IntuitionBase);
X    if (GfxBase) CloseLibrary(GfxBase);
X    return(0);
X}
X
X
X_abort()
X{
X    kill_dps_screen();
X    if (IntuitionBase) CloseLibrary(IntuitionBase);
X    if (GfxBase) CloseLibrary(GfxBase);
X    exit(ERR_ABORT);
X}
X
X
SHAR_EOF
echo "extracting dps.doc"
sed 's/^X//' << \SHAR_EOF > dps.doc
X                                DPS
X                            Version 1.1
X
X                        Author: Allen Norskog
X                           April 23, 1989
X
X
XPUBLIC DOMAIN NOTICE
X
XThis program is placed in Public Domain.  It may be freely copied.
XI developed this program to suit my own needs.  I hope it will be
Xuseful to others.  The source is included so that you can make
Xmodifications to suit your own needs.  I would appreciate any comments
Xor bug reports.
X
X
XDESCRIPTION
X
XDPS is designed to work with the PrintScript program by Pixelations
Xto provide a page previewer.  PrintScript is a PostScript interpreter.
X
XPresently, PrintScript does not include a screen previewer.  This
Xprogram addresses this shortcoming.  PrintScript does have the ability
Xto write a "bitmap" picture to a file.  This program reads in such
Xa file and displays the "page" on the screen.
X
XThe main motivation behind DPS, was to have a tool that would show
Xone's mistakes, such as printing off the page, or not getting things
Xcentered.  For this, one would like something quick.  Generating
Xa file for DPS is not really quick, but can be two to three times
Xfaster than actually printing.
X
XDPS uses a lower resolution picture than what you will probably 
Xfinally print.  The advantage here is that the smaller picture takes 
Xless time to compute.  Also, the picture file takes less disk or 
Xmemory space than if you generated a hi-res image file.
X
XPresently, DPS is set to display one fixed page size -- 8.5 by 11 inches.
XHow it appears on the screen is dependent of course on your monitor.
XWith a standard Amiga monitor, it will actually be a bit larger.  Also
Xthe image will be slightly tall - you will notice this a bit, for
Xexample, when drawing a circle.
X
XOriginally, what I thought I wanted was a full page overview, like that
Xin the "Overview" window.  Since I couldn't get PrintScript to generate
Xless than 72 dpi, I had approximately twice as many dots (pixels) in each 
Xdirection than what I originally wanted.  Having the dots available 
Xanyway, I did the larger main window, and have generally liked it 
Xbetter.  One can see the details much more clearly in the main window.
XThe Overview window is compressed 2X in both directions compared to the
Xmain window.  Each pixel in the Overview image represents 2x2 pixels
Xin the main window.  If any of the pixels in the 2x2 square is black,
Xthe corresponding pixel in the Overview window will be black.  This
Xmakes sure that (normal black) lines don't disappear -- if you are
Xgoing to be printing something in that area, you will see something
Xon the screen.  However, gray areas get darker (or totally black)
Xon the Overview window.
X
X
X
XCONFIGURING PRINTSCRIPT
X
XDPS uses the file output feature of PrintScript.  This file describes
Xthe image in a run-length-encoded manner documented in the PrintScript
Xmanual.  For DPS to work properly, you need to specify that you are
Xgoing to use an 8.5 by 11 inch page, with no margins, and at 72 dots
Xper inch.  
X
XYou need to run the configuration program on the PrintScript disk to
Xcreate a configuration file (Config.ps) that tells PrintScript to write
Xto a file.  See the manual for information.  Below is a sample session:
X
X1> configure
X
XScreen frequency (10-360)? 10            (You may choose from 10 to 72)
XScreen angle (0-90)? 45                  (You may choose 0 to 90)
XAre you using a preferences printer (Y or N)? N
XWidth of printable page in inches (1.0 - 14.0)? 8.5
XHeight of printable page inches (1.0 - 14.0)? 11
XHorizontal dots per inch (72-360)? 72
XVertical dots per inch (72-360)? 72
XPrinter port name or filename (par:, ser: or file)? ram:dps_file
XName of printer driver? File
XUnprintable left margin in inches (0.0 - 1.0)? 0.0
XUnprintable bottom margin in inches (0.0 - 1.0)? 0.0
X
XYou may choose a file name other than ram:dps_file.  Just remember
Xwhat you called it so you know where to find it.  The file generated
Xwill generally not be too large because of the low resolution
Xand the compression used.  Thus, you should be able to usually write it
Xto ram: to speed things up.
X
XThe first two questions in the configuration example shown above 
Xrelate to settings for half-tone images.  You may want to experiment 
Xwith values here.  See the PrintScript manual or a PostScript manual
Xfor more info.
X
XAfter you run PrintScript on your PostScript file, the output file
Xshould be available to use in DPS.
X
X
XRUNNING DPS
X
XDPS can be run from either the CLI (like PrintScript), or from the
XWorkbench.  
X
XFrom the CLI:
X
X    You simply type dps followed by the file name.  If you ran the 
X    configuration as described above, you would enter at the cli prompt:
X
X    1> dps ram:dps_file
X
X
XFrom the Workbench:
X
X    The file that DPS will be looking for is given in the ToolTypes for
X    the DPS icon (info file).  Find the DPS icon.  Click on it once.
X    Select the Workbench-Info menu item from the Workbench screen.  
X    Change the ToolTypes line, so "FILE" is pointed to the file you 
X    want.  For example, if you used the above configuration, you would
X    set the line to be:
X
X    FILE=ram:dps_file
X
X    Save the changes you made to the info file.  Now the DPS icon is
X    ready for use.  Double click on the icon to run DPS.
X
X
XWhen the DPS program is first loaded, it checks if the file specified
Xis really a PrintScript file.  If the file is okay, it will build an
Ximage for display.  DPS will open a custom interlace screen.  A gray
Xpage was chosen to reduce flicker.  The writing on the page will be
Xblack.  A page outline is displayed, so you can see where the "edges"
Xwill be.  If you write to the edge, that area of the edge will be
Xreversed, so you can tell that you are attempting to write there.
XYou are probably too close for what your printer will do.
X
XA slider along the right allows you to scroll up and down the page.
X
XYou can exit DPS by hitting the "close button" in the DPS window, or
Xuse the "Quit" menu option.
X
XAnother menu item is labeled "Overview".  Selecting this will bring
Xup what was intended to be a full page view on the screen.  Actually,
Xit is a couple lines short, so a slider bar is also provided in the
XOverview window as well.  The image in the Overview window is half
Xas wide and half as tall as the image in the main DPS window.  Closing
Xthe Overview window returns you to the main DPS window. 
X
X
XERRORS
X
XThe file you specify will be checked to see if it is a PrintScript
Xtype file.  If the beginning of the file is not set up like it expects
X(see the header definition in the PrintScript manual), it will assume 
Xthat you are trying to read a non-PrintScript file.  DPS will display
Xa message describing the problem and the program will exit.  Actually
XDPS will only require that the "version" be 1 and that "flags" be 1.
XAll the other fields are ignored for now, so it is important that you
Xuse the setup described above.
X
XIf DPS is started from the CLI, any error messages will be displayed
Xin your CLI window.  Thus, you can have a log of any error messages.
XIf the program is started from the Workbench, error messages may
Xbe displayed in requestors, or a text window that displays briefly.
X
X
XMISCELLANEOUS
X
XTo let you try the DPS program, an example file (dps.circle) is
Xincluded.  This file was generate with PrintScript using an adaptation
Xof one of the example programs in the Adobe "PostScript Language
XTutorial and Cookbook".  To try it type at the the CLI prompt:
X
X1> dps dps.circle
X
XOR double click on the dps icon.  The icon has the ToolType set for
X"FILE=dps.circle", so that the demo can be readily seen.  Change
Xthe Tool Type entry as described above for actual use.
X
X
XAllen Norskog
X900 Whaler's Way
XFort Collins, CO  80525
X
X--------------------------
XTrademark acknowledgements
X
XPrintScript is a trademark of Pixelations
XPostScript is a trademark of Adobe Systems, Inc.
SHAR_EOF
echo "End of archive 1 (of 1)"
# if you want to concatenate archives, remove anything after this line
exit