/*
 * 5799-WZQ (C) COPYRIGHT IBM CORPORATION 1988
 * LICENSED MATERIALS - PROPERTY OF IBM
 * REFER TO COPYRIGHT INSTRUCTIONS FORM NUMBER G120-2083
 */
/* $Header:showps.c 12.2$ */
/* $ACIS:showps.c 12.2$ */
/* $Source: /ibm/acis/usr/src/ibm/lpfilter/pp4216/RCS/showps.c,v $ */

#ifndef lint
static char *rcsid = "$Header:showps.c 12.2$";
#endif

#include <stdio.h>
#include <sys/file.h>
#include <sys/types.h>
#include <X11/Xlib.h>
#include "fcntl.h"

#define forever -1
#define NULL 0
#define MIN _min
#define MAX_SIZE 50000  /* largest size of a bit map page accepted */


#define swapbytes(x)    ( ((x&0x0000ff00)>>8) | ((x&0x000000ff)<<8) )


typedef struct noname
        {
        char dfimag00[8];
        short  n_rows;
        short  n_cols;
        char image_type;
        long framelen;
        char spare[12];
        } header, *headptr;

char *malloc();
Window XCreateWindow();

static Window		 picWindow;
static Display 		*display;
static XImage 		*image;
static GC 		 defGC;
static unsigned int 	 pw, ph;
static int        	 winx = 0; 
static int        	 winy = 0;
static int               winh;
static int               winw;
static unsigned long	 border,
			 borderwidth = 5,
			 background;
static int 		 dScreen;
static FILE             *sd;
static char 		*block;
static int 		 curpage = 0;

static char 		*filer;


static void resize() {
    XWindowAttributes atts ;
    XGetWindowAttributes( display, picWindow, &atts );
    winh = atts.height;
    winw = atts.width;
    return ;
}


static void redraw() {
    XClearWindow(display,picWindow);
    return ;
}


static void HandleEvents() {
    off_t  lseek();
    XEvent event;
    int    lastpage;

    	XNextEvent(display,&event);
    	switch(event.type)
    		{
    		case ConfigureNotify:
    			{
    			XConfigureEvent *ce = (XConfigureEvent *)&event;
    			winw = ce->width;
    			winh = ce->height;
    			redraw();
    			} break;
    		case EnterNotify:
    	                break;
    	
    	        case ButtonPress:
    	                break;
    	
    	        case ButtonRelease:
                        lastpage = curpage;
    	                if (event.xbutton.button == 1) {
    	                    curpage++;
    	                }
    	                else if (event.xbutton.button == 3) {
    	                    if (curpage > 0)
    	                        curpage--;
    	                    else
    	                        curpage = 0;
    	                }
    	                else if (event.xbutton.button == 2) {
    	                    fclose(sd);
    	                    exit(0);
    	                }
    	                fseek(sd, (off_t)(sizeof(header) + 
                                ((ph*pw/8)*curpage)), 0);
    	                if (fread(block, ph*pw/8, 1, sd) <= 0)
                            curpage = lastpage; 
                        else {
    	                    putframe(display, dScreen, block);
    	                    XMapWindow(display, picWindow);
    	                    redraw();
                        }
    			break;
    	
    		case LeaveNotify:
    	/*		XUninstallColormap(display, cmap); */
    			break;
    		case MapNotify:
    			resize();
    			redraw();
    			break;
    		case Expose:
    			{
    			int cnt;
    			XExposeEvent *ee = (XExposeEvent *)&event;
    			cnt = ee->count;
    			while(cnt--) 
    	                    XNextEvent(display, &event);
    			resize();
    			redraw();
    			} break;
    		case UnmapNotify: /*BLOCK UNTIL REMAPPED */
    			do {
    	                    XNextEvent(display,&event);
    	                }
    		        while(event.type != MapNotify);
    			resize();
    			redraw();
    			break;
                case NoExpose:
                        {
		        } break;
    		default: printf("Zip: weird event %d\n",event.type);
    			break;
    		}
    	    return ;
    	}
    
	
main(argc, argv)
char **argv;
{
    int i,j;
    char *server = NULL;
    header head;

    extern char *getenv() ;

    i=1;
    /* process options */
    if ((i < argc) && !strcmp(argv[i],"-display")) {
        i++;
        server=argv[i++]; 
    }
    filer = NULL;
    if (i < argc) {
        filer = argv[i];
    }

    if ( !server )
	server = getenv("DISPLAY");
    if ( !server )
	server = ":0" ;

    if (!(display = XOpenDisplay(server))) {
    	fprintf(stderr, "Cannot open display\n"); 
        exit(1); 
    }

    dScreen = DefaultScreen(display);

    
    if (filer != NULL) {
        sd = fopen(filer,"r");
    }
    else {
        sd = fdopen(0,"r");
        filer = "stdin";
    }
    
    if (sd == NULL) {
        fprintf(stderr, "Error opening %s\n",filer);
        return;
    }
    
    j = sizeof(header);
    fread((char *)&head, j, 1, sd);
    pw = swapbytes(head.n_cols);
    ph = swapbytes(head.n_rows);
    
    if (ph*pw/8 > MAX_SIZE) {
        fprintf(stderr,"Showps: Invalid header in file %s\n",filer);
        exit(1);
    }
    block = malloc(ph*pw/8);
    if (block == NULL) {
        perror("showps");
        exit(1);
    }
    fread(block, ph*pw/8, 1, sd); 
    
    border = BlackPixel(display, dScreen);
    background = WhitePixel(display, dScreen);
    picWindow = XCreateSimpleWindow(display,
		RootWindow(display, dScreen),
		winx, winy, pw, ph,
 		borderwidth, border,
		background);
    putframe(display, dScreen, block);
    XMapWindow(display, picWindow);
    redraw();

    while (forever)
	HandleEvents();
  
    fclose(sd);
    exit( 0 ) ;
    /*NOTREACHED*/
}



static putframe(display, screen, block)   
     Display *display;
     int screen;
     char *block;    

{
    Pixmap BackMap;


    BackMap = XCreatePixmap(display, picWindow, pw, ph, 1);

    image = (XImage *) XCreateImage( display,
				     DefaultVisual( display,
						    DefaultScreen( display ) ),
				     1, XYBitmap,
			 	     0, block, pw, ph,
				     BitmapPad( display ), 0 ) ;

    defGC = XCreateGC(display, BackMap, 0, NULL); 
    if (defGC==0)
    	{
    	fprintf(stderr, "error creating GC\n");
    	_exit(1);
    	}

    XSetForeground(display, defGC,  BlackPixel(display, screen));
    XSetBackground(display, defGC,  WhitePixel(display, screen));

    /* Now Check If Server Is Mono or Color ?? */
    if ( DefaultDepth( display, screen ) != 1 ) {
        XSetFunction(display, defGC, GXcopyInverted); 
    }

    XPutImage(display,BackMap,defGC,image,0, 0, 0,0, pw, ph);
    XDestroyImage(image);

    /* Now Check If Server Is Mono or Color ?? */
    if ( DefaultDepth( display, screen ) != 1 ) {
	Pixmap BWBackMap = BackMap ;
	GC BWGC = defGC ;
	BackMap = XCreatePixmap( display, picWindow,
				 pw, ph,
				 DefaultDepth( display, screen ) ) ;

	defGC = DefaultGC( display, screen );
        XSetForeground(display, defGC,  BlackPixel(display, screen));
        XSetBackground(display, defGC,  WhitePixel(display, screen));

	XCopyPlane( display, BWBackMap, BackMap,
		        defGC, 0, 0, pw, ph, 0, 0, 1 );
	XFreePixmap( display, BWBackMap ) ;
	XFreeGC( display, BWGC ) ; 
    }
    XSetWindowBackgroundPixmap(display, picWindow, BackMap);

    XStoreName(display,picWindow,filer);
    XSetIconName(display,picWindow,filer);
    XSelectInput(display,picWindow,
	             EnterWindowMask   | LeaveWindowMask | 
                     ButtonReleaseMask | ButtonPressMask );
}
