[comp.sources.misc] v09i048: popi, The Digital Darkroom, Part02/09

richb@sunaus.sun.oz.AU (Rich Burridge) (12/13/89)

Posting-number: Volume 9, Issue 48
Submitted-by: Rich Burridge <richb@sunaus.sun.oz.AU>
Archive-name: popi/part02

---- Cut Here and unpack ----
#!/bin/sh
# this is part 2 of a multipart archive
# do not concatenate these parts, unpack them in order with /bin/sh
# file expr.c continued
#
CurArch=2
if test ! -r s2_seq_.tmp
then echo "Please unpack part 1 first!"
     exit 1; fi
( read Scheck
  if test "$Scheck" != $CurArch
  then echo "Please unpack part $Scheck next!"
       exit 1;
  else exit 0; fi
) < s2_seq_.tmp || exit 1
echo "x - Continuing file expr.c"
sed 's/^X//' << 'Funky_Stuff' >> expr.c
Xstatic
X#endif	/* __MSC__ */
Xvoid
Xexpr()
X{
X    extern int	prs;
X    int		remem1,
X		remem2;
X
X    DEBUG((Debug, "expr() lat='%c'\n", lat));
X    DEBUG((Debug, "levels of precedence: %d\n", PREC_LEVELS));
X
X    level(PREC_LEVELS - 1);
X
X    if (lat == '?')
X    {
X	lex();
X	emit('?');
X	remem1 = prs;
X	emit(0);
X	expr();
X	expect(':');
X	emit(':');
X	remem2 = prs;
X	emit(0);
X	parsed[remem1] = prs-1;
X	expr();
X	parsed[remem2] = prs-1;
X    }
X}
X
X
Xvoid
Xexpect(t)
Xint t;
X{
X    DEBUG((Debug, "expect('%c')\n", t));
X
X    if (lat == t)
X	lex();
X    else
X    {
X	if (t < 127)
X	    SPRINTF(ErrBuf, "expected token '%c' (%d)", t, t);
X	else
X	    SPRINTF(ErrBuf, "expected token (%d)", t);
X	error(ERR_PARSE);
X    }
X}
X
X/*
X * Transform	=	NEW '[' index ']' '=' expr
X *		|	NEW '=' expr
X *		|	expr
X */
Xvoid
Xtransform()
X{
X    extern int prs;
X
X    DEBUG((Debug, "transform() lat='%c'\n", lat));
X
X    prs = 0 ;     /* initial length of parse string */
X    if (lat != NEW)
X    {
X	expr();
X	emit('@');
X    }
X    else
X    {
X	lex();
X	if (lat == '[')
X	{
X	    fileref(CURNEW, CLVAL);
X	    expect('=');
X	    expr();
X	    emit('=');
X	}
X	else
X	{
X	    expect('=');
X	    expr();
X	    emit('@');
X	}
X    }
X    if (lat != '\n')
X    {
X	SPRINTF(ErrBuf,
X	    "syntax error - expected operator or end of expression");
X	error(ERR_PARSE);
X    }
X    assert(lat == '\n');
X}
Funky_Stuff
echo "File expr.c is complete"
chmod 0444 expr.c || echo "restore of expr.c fails"
set `wc -c expr.c`;Sum=$1
if test "$Sum" != "8806"
then echo original size 8806, current size $Sum;fi
echo "x - extracting ibmpc.c (Text)"
sed 's/^X//' << 'Funky_Stuff' > ibmpc.c &&
X/*LINTLIBRARY*/
X#ifndef	lint
Xstatic char sccsid[] = "@(#)ibmpc.c 1.4 89/12/12" ;
X#endif
X
X/*  Popi device driver for a PC using one of:
X *	Borland Turbo C
X *	Microsoft C
X *	MIX Power C
X *  Written by Stephen Frede, Softway Pty Ltd.
X *
X *  Popi was originally written by Gerard J. Holzmann - AT&T Bell Labs.
X *  This version is based on the code in his Prentice Hall book,
X *  "Beyond Photography - the digital darkroom," ISBN 0-13-074410-7,
X *  which is copyright (c) 1988 by Bell Telephone Laboratories, Inc. 
X *
X *  Permission is given to distribute these extensions, as long as these
X *  introductory messages are not removed, and no monies are exchanged.
X *
X *  No responsibility is taken for any errors or inaccuracies inherent
X *  either to the comments or the code of this program, but if reported
X *  (see README file) then an attempt will be made to fix them.
X */
X
X/*
X *  There is still some work to be done here:
X *	+ vid_detect() needs to be written.
X *	+ HGC code needs to be fixed properly.
X *	+ other standard modes need to be added.
X *	+ Dithering or something needs to be added for EGA (sim to CGA).
X *	+ Handle image allocation properly with far pointers
X *		where appropriate (ie unavoidable).
X */
X
X#if defined(__STDC__) && defined(__TURBOC__)
X/* The user has (with commendable intentions) used the Turbo C
X * ANSI compatibility flag. Unfortunately, we need the nonstandard
X * extensions to include <graphics.h> and use far pointers.
X */
X#include "Unfortunately, can't use ANSI compatibility flag."
X#endif	/* __STDC__ && __TURBOC__ */
X
X#include "popi.h"
X
X/* I don't know what token Power C defines to distinguish itself.
X * But it does define a max() macro in stdlib.h include file.
X * Hopefully no other vendor is silly enough to do this, so we
X * can use that to distinguish Power C.
X */
X#if	defined(__STDC__) && defined(max)
X#define	__POWERC__	1
X#endif	/* __STDC__ && max */
X
X/* We assume that the compiler has these files header files. */
X#include <dos.h>
X#include <conio.h>
X
X/* We only use the __TURBOC__ token to test for graphics related
X * features from here on, so if we have an old version with no
X * graphics support, just pretend we are a generic compiler.
X */
X#if defined(__TURBOC__)
X# if __TURBOC__ < 0x0200
X#  undef	__TURBOC__
X# endif	/* __TURBOC__ < 0x0200 */
X#endif	/* __TURBOC__ */
X
X#if __TURBOC__ || __POWERC__
X# include <graphics.h>
X#endif /* __TURBOC__ || __POWERC__ */
X
X#if	__MSC__
X#include <graph.h>
X#endif	/* __MSC__ */
X
X
X#if	defined(__TURBOC__)
X# ifndef	BGIPATH
X#  define	STRBGIPATH	""
X# else
X#  define	STR(x)	#x
X#  define	STRBGIPATH	STR(BGIPATH)
X# endif	/* BGIPATH */
X#endif /* __TURBOC__ */
X
X#ifndef MK_FP
X#define MK_FP(segment,offset)	((void far *) \
X			   (((unsigned long)(segment) << 16) | (unsigned)(offset)))
X#endif	/* MK_FP */
X
X/*  There are ten exportable routines used by the popi program.
X *
X *  These are:
X *
X *  disp_init(argc, argv)	- called from main at the start.
X *  disp_finish()		- called from main prior to exit.
X *  disp_imgstart()		- called prior to drawing an image.
X *  disp_imgend()		- called after drawing an image.
X *  disp_putline(line, y)	- to draw an image scanline.
X *  disp_getchar()		- to get the next character typed.
X *  disp_ungetc(c)		- put back the last character typed.
X *  disp_prompt()		- display popi prompt and clear input buffer.
X *  disp_error(errtype,pos)	- display error message.
X *  disp_percentdone(n)		- display percentage value of conversion.
X */
X
X/*
X *	Bios function call definitions
X */
X
X#define	BIOS_VIDFN		0x10	/* Video functions */
X#define VID_PALETTE		0x10	/* palette access function */
X#define PAL_SETPAL		0x00	/* update single palette register */
X#define PAL_SETPALBLOCK		0x02	/* update all palette registers */
X#define PAL_GETPALBLOCK		0x09	/* read all palette registers */
X#define PAL_GETDACBLOCK		0x17	/* read current VGA DAC values */
X#define PAL_SETDACBLOCK		0x12	/* set new VGA DAC values */
X
X/*
X *	Arguments to the vid_vgapalette and vid_setpalette functions
X */
X#define	PAL_SAVE		0	/* Save existing values */
X#define	PAL_RESTORE		1	/* Restore saved values */
X#define	PAL_SETGREY		2	/* Set greyscale mapping */
X#define	PAL_SETLIN		3	/* Set 1:1 mapping (vid_setpalette) */
X
X/* Bios Addresses */
X#define SEG_VIDBIOS		0x0040	/* Segment of video BIOS addresses */
X#define BIOSADDR_MODE		0x0049	/* Current BIOS video mode number */
X#define BIOSADDR_CRTCPORT	0x0063	/* Port Address of CRTC */
X
X/* Fixed port addresses */
X#define	HGC_SWITCH	0x03BF
X
X
X/* Prototypes for local functions */
Xvoid	vid_vgapalette P((int));
Xvoid	vid_setpalette P((int));
Xvoid	vid_setmode P((unsigned char));
Xvoid	vid_sethgc P((void));
Xvoid	vid_setpixel P((int, int, pixel_t));
Xunsigned char	vid_detect P((void));
X
X	/* Array containing threshold values for dithering. */
Xpixel_t thresh[BITSPERPIXEL][BITSPERPIXEL] =
X{
X    {	0, 128,	 32, 160,   8, 136,  40, 168, },
X    { 192,  64,	224,  96, 200,	72, 232, 104, },
X    {  48, 176,	 16, 144,  56, 184,  24, 152, },
X    { 240, 112,	208,  80, 248, 120, 216,  88, },
X    {  12, 140,	 44, 172,   4, 132,  36, 164, },
X    { 204,  76,	236, 108, 196,	68, 228, 100, },
X    {  60, 188,	 28, 156,  52, 180,  20, 148, },
X    { 252, 124,	220,  92, 244, 116, 212,  84, },
X};
X
Xstruct VidDriver
X{
X    unsigned char	bios_mode;	/* Bios mode no. */
X    unsigned int	xsize,		/* Pixels/scanline */
X    			ysize;		/* Scanlines/image */
X    /* Segment to which screen buffer is mapped */
X    unsigned int	ScreenMem;
X    unsigned int	interlace,	/* no. lines interlaced */
X    			interlace_offset; /* memory offset for interlace */
X    unsigned char	PixelsPerByte;
X};
X
Xstatic struct VidDriver	VidDrivers[] =
X{
X#define VID_VGA	0
X    {
X        0x13, 320, 200, 0xA000, 1, 0, 1,
X    },
X#define VID_EGA	1
X    {
X        0x10, 640, 350, 0xA000, 2, 0x2000, 8,
X    },
X#define VID_CGA	2
X    {
X        0x06, 640, 200, 0xB800, 2, 0x2000, 8,
X    },
X#define VID_STD	2	/* Last standard adapter */
X/* From here on, adapters have no bios support. The bios
X * number will be stored in the appropriate place in the video
X * bios data area (this is useful eg if a mouse is being used,
X * so it gets the graphics cursor correct).
X */
X#define VID_HGC	3
X    {
X        0x06, 720, 348, 0xB000, 4, 0x2000, 8,
X    },
X};
X#define	VID_NONE	-1	/* Unknown video adapter */
X/* When VidAdapter is VID_LIB, use compile-time dependant
X * library routines. For example, the Turbo C graphics library
X * allows custom drivers to be added for nonstandard adapters.
X */
X#define	VID_LIB		-2
X
Xstatic struct VidDriver
X	*VidDriver = 0;
X
Xstatic int
X	VidAdapter = VID_NONE,
X	vid_xbytes,
X	vid_xoff_bytes,
X	vid_yoff;
X#if __TURBOC__
Xstatic int
X	tc_driver,
X	tc_mode,
X	tc_error;
X#endif	/* __TURBOC__ */
X
Xstatic unsigned char far
X	*ScreenMem;
X/* Pointer to current mode in Bios video display data area */
Xstatic char far
X	*VidModeBiosAddr = MK_FP(SEG_VIDBIOS, BIOSADDR_MODE);
X/* Pointer to CRTC register port number in Bios dideo display area */
Xstatic short far
X	*CrtcPortBiosAddr = MK_FP(SEG_VIDBIOS, BIOSADDR_CRTCPORT);
Xstatic char
X	VidInitMode;
X
X/*
X *	Routine to map VGA palette registers (256 colour mode)
X *	to and from a greyscale display.
X */
X#define BITSPERBYTE		8
X#define BITSPERVGACOLOUR	6
X				/* no. VGA DAC registers */
X#define SIZE_DACS		256
X				/* no. distinct greyscale values */
X#define NUM_GREY		(1 << BITSPERVGACOLOUR)
X				/* no. palette registers that map
X				 * to the same greyscale value */
X#define GREY_SAME		(SIZE_DACS / NUM_GREY)
X				/* no. underlying colours on vga */
X#define PRIMARY_COLOURS		3
X
Xstatic void
Xvid_vgapalette(action)
Xint	action;
X{
X    union REGS			regs;
X    struct SREGS		sreg;
X    static unsigned char	SaveDacs[SIZE_DACS * PRIMARY_COLOURS],
X    				*GreyDacs = 0;
X
X    switch(action)
X    {
X    	case PAL_SAVE:
X	    /* Save existing palette */
X	    regs.h.ah = VID_PALETTE;
X	    regs.h.al = PAL_GETPALBLOCK;
X	    regs.x.bx = 0;		/* first palette register */
X	    regs.x.cx = SIZE_DACS;	/* read all palette registers */
X	    segread(&sreg);
X	    sreg.es = sreg.ds;
X	    regs.x.dx = (unsigned int) SaveDacs;
X	    int86x(BIOS_VIDFN, &regs, &regs, &sreg);
X	    break;
X
X	case PAL_RESTORE:
X	    /* restore saved palette */
X	    regs.h.ah = VID_PALETTE;
X	    regs.h.al = PAL_SETDACBLOCK;
X	    regs.x.bx = 0;		/* first palette register */
X	    regs.x.cx = SIZE_DACS;	/* read all palette registers */
X	    segread(&sreg);
X	    sreg.es = sreg.ds;
X	    regs.x.dx = (unsigned int) SaveDacs;
X	    int86x(BIOS_VIDFN, &regs, &regs, &sreg);
X	    break;
X
X	case PAL_SETGREY:
X	    /* set palette to greyscale */
X	    if (GreyDacs == 0)
X	    {
X		unsigned char	*p,
X				c;
X
X	    	if ((GreyDacs = malloc(SIZE_DACS*PRIMARY_COLOURS))
X			== 0)
X		{
X		    sprintf(ErrBuf, "Dacs allocation failed");
X		    error(ERR_SYS);
X		    return;
X		}
X		for (p = GreyDacs, c = 0; c < NUM_GREY; ++c)
X		{
X		    int		i;
X
X		    for (i = 0; i < PRIMARY_COLOURS * GREY_SAME; ++i)
X			*p++ = c;
X		}
X	    }
X	    regs.h.ah = VID_PALETTE;
X	    regs.h.al = PAL_SETDACBLOCK;
X	    regs.x.bx = 0;		/* first palette register */
X	    regs.x.cx = SIZE_DACS;	/* read all palette registers */
X	    segread(&sreg);
X	    sreg.es = sreg.ds;
X	    regs.x.dx = (unsigned int) GreyDacs;
X	    int86x(BIOS_VIDFN, &regs, &regs, &sreg);
X	    break;
X    }
X}
X
X/*
X *	Routine to map 16 palette registers.
X */
X
X#define SIZE_PALETTE		17	/* 16 + overscan */
X
Xstatic void
Xvid_setpalette(action)
Xint	action;
X{
X    union REGS			regs;
X    struct SREGS		sreg;
X    static unsigned char	SavePalette[SIZE_PALETTE],
X    				*GreyPalette = 0;
X    unsigned char		palette;
X
X    switch (action)
X    {
X        case PAL_SAVE:
X	    /* Save existing palette */
X	    regs.h.ah = VID_PALETTE;
X	    regs.h.al = PAL_GETPALBLOCK;
X	    segread(&sreg);
X	    sreg.es = sreg.ds;
X	    regs.x.dx = (unsigned int) SavePalette;
X	    int86x(BIOS_VIDFN, &regs, &regs, &sreg);
X	    break;
X
X	case PAL_RESTORE:
X	    /* restore saved palette */
X	    regs.h.ah = VID_PALETTE;
X	    regs.h.al = PAL_SETPALBLOCK;
X	    segread(&sreg);
X	    sreg.es = sreg.ds;
X	    regs.x.dx = (unsigned int) SavePalette;
X	    int86x(BIOS_VIDFN, &regs, &regs, &sreg);
X	    break;
X
X	case PAL_SETGREY:
X	    /* set palette to greyscale */
X	    if (GreyPalette == 0)
X	    {
X		if ((GreyPalette = (unsigned char *) malloc(SIZE_PALETTE)) == 0)
X		{
X		    sprintf(ErrBuf, "Palette allocation failed");
X		    error(ERR_SYS);
X		    return;
X		}
X		GreyPalette[0] = 000;
X		GreyPalette[1] = 070;
X		GreyPalette[2] = 007;
X		GreyPalette[3] = 077;
X		GreyPalette[SIZE_PALETTE-1] = SavePalette[SIZE_PALETTE-1];
X	    }
X	    regs.h.ah = VID_PALETTE;
X	    regs.h.al = PAL_SETPALBLOCK;
X	    segread(&sreg);
X	    sreg.es = sreg.ds;
X	    regs.x.dx = (unsigned int) GreyPalette;
X	    int86x(BIOS_VIDFN, &regs, &regs, &sreg);
X	    break;
X
X	case PAL_SETLIN:
X	    for (palette = 0; palette < SIZE_PALETTE; ++palette)
X	    {
X		union REGS regs;
X
X		regs.h.ah = VID_PALETTE;
X		regs.h.al = PAL_SETPAL;
X		regs.h.bh = palette;
X		regs.h.bl = palette;
X		int86(BIOS_VIDFN, &regs, &regs);
X	    }
X	    break;
X    }
X}
X
Xstatic void
Xvid_setmode(mode)
Xunsigned char	mode;
X{
X	union REGS	regs;
X
X	regs.h.ah = 0;
X	regs.h.al = mode;
X	int86(0x10, &regs, &regs);
X}
X
Xstatic void
Xvid_setpixel(x, y, value)
Xint x, y;
Xpixel_t value;
X{
X	union REGS	regs;
X
X	regs.h.al = value;
X	regs.h.ah = 0x0C;
X	regs.h.bh = 0;
X	regs.x.cx = (unsigned) x;
X	regs.x.dx = (unsigned) y;
X	int86(0x10, &regs, &regs);
X}
X
X/*
X *	Detect installed graphics hardware.
X */
Xstatic unsigned char
Xvid_detect()
X{
X    /* Yes, well, when I get a chance I'll do this.
X     * Wait for the next release.
X     */
X    return VID_NONE;
X}
X
X/*ARGSUSED*/
Xvoid
Xdisp_init(argc,argv)		/* called from main at the start. */
Xint argc;
Xchar *argv[];
X{
X   /* Some compilers (eg Power C) don't get the initialisation right,
X    * so repeat it here.
X    */
X    VidModeBiosAddr = MK_FP(SEG_VIDBIOS, BIOSADDR_MODE);
X    CrtcPortBiosAddr = MK_FP(SEG_VIDBIOS, BIOSADDR_CRTCPORT);
X    VidInitMode = *VidModeBiosAddr;
X
X    VidAdapter = vid_detect();
X
X#if	__TURBOC__
X    tc_driver = DETECT;
X    detectgraph(&tc_driver, &tc_mode);
X
X    switch (tc_driver)
X    {
X	case VGA:
X	    VidAdapter = VID_VGA;
X	    break;
X
X	case EGA:
X	case EGA64:
X	    VidAdapter = VID_EGA;
X	    break;
X
X	case CGA:
X	    VidAdapter = VID_CGA;
X	    break;
X
X	default:
X	    initgraph(&tc_driver, &tc_mode, STRBGIPATH);
X	    tc_error = graphresult();
X	    if (tc_error < 0)
X	    {
X		sprintf(ErrBuf, "initgraph error (%s)",
X		    grapherrormsg(tc_error));
X		error(ERR_WARN);
X		VidAdapter = VID_NONE;
X		return;
X	    }
X	    else
X		VidAdapter = VID_LIB;
X    }
X#endif	/* __TURBOC__ */
X
X#if	__MSC__
X    if (_setvideomode(_VRES2COLOR))
X    	VidAdapter = VID_VGA;
X    else if (_setvideomode(_ERESNOCOLOR))
X    	VidAdapter = VID_EGA;
X    else if (_setvideomode(_HRESBW))
X    	;
X    else
X	VidAdapter = VID_NONE;
X#endif	/* __MSC__ */
X
X#if	__POWERC__
X    if (setvmode(17) == 17)
X    	VidAdapter = VID_VGA;
X    else if (setvmode(15) == 15)
X    	VidAdapter = VID_EGA;
X    else if (setvmode(6) == 6)
X    	VidAdapter = VID_CGA;
X    else if (setvmode(99) == 99)
X    	VidAdapter = VID_HGC;
X#endif	/* __POWERC__ */
X
X    /* This is also a last minute addition that needs to
X     * be cleaned up - again, next release.
X     */
X    for (++argv; *argv; ++argv)
X    {
X	char	*card;
X
X	if (**argv == '-')
X	    switch ((*argv)[1])
X	    {
X		case 'c':	/* card */
X		    card = *argv + 2;
X		    if (strcmp(card, "vga") == 0)
X		    	VidAdapter = VID_VGA;
X		    else if (strcmp(card, "ega") == 0)
X		    	VidAdapter = VID_EGA;
X		    else if (strcmp(card, "cga") == 0)
X		    	VidAdapter = VID_CGA;
X		    else if (strcmp(card, "hgc") == 0)
X		    	VidAdapter = VID_HGC;
X		    else if (strcmp(card, "lib") == 0)
X		    	VidAdapter = VID_LIB;
X	    }
X    }
X
X    if (VidAdapter == VID_NONE)
X    {
X	vid_setmode(VidInitMode);
X	sprintf(ErrBuf,	"No graphics hardware detected");
X	error(ERR_WARN);
X	return;
X    }
X
X    switch (VidAdapter)
X    {
X	case VID_LIB:
X	    return;
X
X	case VID_VGA:
X	    vid_setpalette(PAL_SAVE);
X	    vid_setpalette(PAL_SETLIN);/**/
X	    vid_vgapalette(PAL_SAVE);
X    	    break;
X
X	case VID_EGA:
X	    vid_setpalette(PAL_SAVE);
X	    break;
X
X	case VID_CGA:
X	    break;
X    }
X
X    vid_setmode(VidInitMode);
X
X    VidDriver = &VidDrivers[VidAdapter];
X    if (Xsize > VidDriver->xsize)
X	Xsize = VidDriver->xsize;
X    if (Ysize > VidDriver->ysize)
X	Ysize = VidDriver->ysize;
X    vid_xbytes = VidDriver->xsize / VidDriver->PixelsPerByte;
X    vid_yoff = (VidDriver->ysize - Ysize) / 2;
X    vid_xoff_bytes =
X    	((VidDriver->xsize - Xsize) / 2) / VidDriver->PixelsPerByte;
X    ScreenMem = MK_FP(VidDriver->ScreenMem, 0);
X}
X
Xvoid
Xdisp_finish()			/* called from main prior to exit. */
X{
X#if	__TURBOC__
X    if (VidAdapter == VID_LIB)
X	closegraph();
X#endif	/* __TURBOC__ */
X}
X
X/*
X *	Set up Hercules Graphics Card 720 * 348 graphics mode
X */
Xstatic void
Xvid_sethgc()
X{
X    unsigned short	ModeControl = 0x03b8;
X    unsigned short	CrtcAddress = 0x03b4;
X    unsigned short	CrtcData = CrtcAddress + 1;
X
X    outportb(HGC_SWITCH, 0x01);		/* allow graphics mode */
X    outportb(ModeControl, 0x00);	/* Video disabled during setup */
X
X    /* Horizontal total: 54 "characters" (at 16 pixels/char) */
X    outportb(CrtcAddress, 0x00);
X    outportb(CrtcData, 0x35);
X    /* Horizontal displayed: 45 "characters" */
X    outportb(CrtcAddress, 0x01);
X    outportb(CrtcData, 0x2d);
X    /* Horizontal sync position: at 45th character */
X    outportb(CrtcAddress, 0x02);
X    outportb(CrtcData, 0x2e);
X    /* Horizontal sync width: 7 character clocks */
X    outportb(CrtcAddress, 0x03);
X    outportb(CrtcData, 0x07);
X    /* Vertical total: 94 "characters" (at 4 scanlines/char) */
X    outportb(CrtcAddress, 0x04);
X    outportb(CrtcData, 0x5b);
X    /* Vertical adjust: 2 scanlines */
X    outportb(CrtcAddress, 0x05);
X    outportb(CrtcData, 0x02);
X    /* Vertical displayed: 87 "character" rows */
X    outportb(CrtcAddress, 0x06);
X    outportb(CrtcData, 0x57);
X    /* Vertical sync position: after 87th char row */
X    outportb(CrtcAddress, 0x07);
X    outportb(CrtcData, 0x57);
X    /* Max scan line: 4 lines/char */
X    outportb(CrtcAddress, 0x09);
X    outportb(CrtcData, 0x03);
X
X    *VidModeBiosAddr = 6;	/* Microsoft mouse: HGC using CRT page 0 */
X
X    outportb(ModeControl, 0x0a);	/* Video enabled, Graphics mode */
X}
X
Xvoid
Xdisp_imgstart()			/* called prior to drawing an image. */
X{
X    if (VidAdapter == VID_NONE)
X	return;
X
X    if (VidAdapter == VID_LIB)
X    {
X#if __TURBOC__
X	setgraphmode(tc_mode);
X#endif	/* __TURBOC__ */
X	return;
X    }
X
X    if (VidAdapter <= VID_STD)
X	vid_setmode(VidDriver->bios_mode);
X    else
X	*VidModeBiosAddr = VidDriver->bios_mode;	/* fake it */
X
X    switch (VidAdapter)
X    {
X	case VID_VGA:
X	    vid_vgapalette(PAL_SETGREY);
X	    break;
X
X	case VID_EGA:
X	    vid_setpalette(PAL_SETGREY);
X	    break;
X
X	case VID_HGC:
X	    vid_sethgc();
X	    break;
X    }
X}
X
Xvoid
Xdisp_imgend()			/* called after drawing an image. */
X{
X    (void) getch();
X
X    switch (VidAdapter)
X    {
X	case VID_VGA:
X	    vid_vgapalette(PAL_RESTORE);
X	    vid_setpalette(PAL_RESTORE);
X	    break;
X
X	case VID_EGA:
X	    vid_setpalette(PAL_RESTORE);
X	    break;
X    }
X
X    vid_setmode(VidInitMode);
X}
X
Xvoid
Xdisp_putline(line, y)		/* called to draw image scanline y. */
Xpixel_t *line;
Xint y;
X{
X    register int		x;
X    register unsigned char far	*p;
X
X    if (VidAdapter == VID_NONE)
X	return;
X
X    if (VidAdapter == VID_LIB)
X    {
X	for (x = 0; x < Xsize; ++x)
X	{
X	    pixel_t	val;
X
X	    val = *line++ < thresh[y % BITSPERPIXEL][x % BITSPERPIXEL] ?
X			(pixel_t) 0 : (pixel_t) 1;
X#if __TURBOC__
X	    putpixel(x, y, val);
X#endif	/* __TURBOC__ */
X#if __MSC__
X	    _setcolor(val);
X	    _setpixel(x, y);
X#endif	/* __MSC__ */
X#if __POWERC__
X	    pen_color(val);
X	    setpixel(x, y);
X#endif	/* __POWERC__ */
X	}
X	return;
X    }
X
X    p = &ScreenMem[
X			(
X			    ((y + vid_yoff) % VidDriver->interlace)
X			    *
X			    VidDriver->interlace_offset
X			)
X			+
X			(y + vid_yoff) / VidDriver->interlace * vid_xbytes
X			/*
X			+
X			vid_xoff_bytes
X			*/
X		];
X
X    switch (VidAdapter)
X    {
X	case VID_VGA:
X	    for (x = 0; x < Xsize; ++x)
X		*p++ = *line++;
X	    break;
X
X	case VID_EGA:
X	    /* 4 grey levels isn't enough - need to do dithering as well,
X	     * or perhaps fake it with some colours.
X	     */
X	    for (x = 0; x < Xsize; ++x)
X		vid_setpixel(x, y, *line++ / 64);
X	    break;
X
X	case VID_CGA:
X	    for (x = 0; x < Xsize;)
X	    {
X		register unsigned char	t;
X		register unsigned char	val;
X		register unsigned char	byte;
X		register int		pixel;
X
X		byte = 0;
X		for (pixel = 8; pixel > 0; ++x)
X		{
X		    t = thresh[y % BITSPERPIXEL][x % BITSPERPIXEL];
X		    val = *line++;
X		    byte |= (val > t * 2 / 3 ? 1 : 0) << --pixel;
X		    byte |= (val > (t * 2 + Zsize) / 3 ? 1 : 0) << --pixel;
X		}
X		*p++ = byte;
X	    }
X	    break;
X
X	case VID_HGC:
X	    for (x = 0; x < Xsize;)
X	    {
X		register char	t;
X		register unsigned char	byte;
X		register int		pixel;
X
X		byte = 0;
X		for (pixel = 8; pixel > 0; ++x)
X		{
X		    t = *line++ < thresh[y % BITSPERPIXEL][x % BITSPERPIXEL] ?
X			(pixel_t) 0 : (pixel_t) 1;
X		    byte |= t << --pixel;
X		}
X		*p++ = byte;
X	    }
X	    break;
X    }
X}
X
Xint
Xdisp_getchar()			/* get next user typed character. */
X{
X    return(getchar());
X}
X
X
X/*ARGSUSED*/
Xvoid
Xdisp_ungetc(c)			/* put back the last character typed. */
Xint c;
X{
X    UNGETC(c, stdin);
X}
X
Xint
Xdisp_prompt()			/* display popi prompt. */
X{
X    char	*prompt = "-> ";
X
X    PRINTF(prompt);
X    return sizeof prompt - 1;
X}
X
Xvoid
Xdisp_error(errtype, pos)	/* display error message. */
Xint	errtype,
X	pos;
X{
X    extern int	errno;
X    extern char	*sys_errlist[];
X
X    if (errtype	& ERR_PARSE)
X    {
X	int	i;
X
X	for (i=1; i < pos; ++i)
X	    PUTC('-', stderr);
X	PUTC('^', stderr);
X	PUTC('\n', stderr);
X    }
X
X    FPRINTF(stderr, "%s\n", ErrBuf);
X    /* we assume errno hasn't been reset by the	preceding output */
X    if (errtype	& ERR_SYS)
X	FPRINTF(stderr,	"\t(%s)\n", sys_errlist[errno]);
X}
X
Xvoid
Xdisp_percentdone(percent)
Xint	percent;
X{
X    static int	lastpercent = 100;
X
X    if (!Verbose)
X	return;
X    if (percent	== 100)
X    {
X	printf("\r    \n");
X	return;
X    }
X    if (percent	!= lastpercent)
X    {
X	printf("\r%2d%%	", percent);
X	fflush(stdout);
X	lastpercent = percent;
X    }
X}
Funky_Stuff
chmod 0444 ibmpc.c || echo "restore of ibmpc.c fails"
set `wc -c ibmpc.c`;Sum=$1
if test "$Sum" != "20056"
then echo original size 20056, current size $Sum;fi
echo "x - extracting io.c (Text)"
sed 's/^X//' << 'Funky_Stuff' > io.c &&
X/*  @(#)io.c 1.8 89/12/11
X *
X *  File handling routines used by the popi program.
X *
X *  Popi was originally written by Gerard J. Holzmann - AT&T Bell Labs.
X *  This version is based on the code in his Prentice Hall book,
X *  "Beyond Photography - the digital darkroom," ISBN 0-13-074410-7,
X *  which is copyright (c) 1988 by Bell Telephone Laboratories, Inc. 
X *
X *  Permission is given to distribute these extensions, as long as these
X *  introductory messages are not removed, and no monies are exchanged.
X *
X *  No responsibility is taken for any errors or inaccuracies inherent
X *  either to the comments or the code of this program, but if reported
X *  (see README file) then an attempt will be made to fix them.
X */
X
X
X#include <stdio.h>
X#include <errno.h>
X#include <ctype.h>
X#include "popi.h"
X
X#if unix || AMIGA
X#define RMODE	"r"
X#define WMODE	"w"
X#else	/* ! (unix || AMIGA) */
X#define RMODE	"rb"
X#define WMODE	"wb"
X#endif	/* unix || AMIGA */
X
Xint		nsrc = 2;
Xstatic int	IsPopen = 0;
X
Xpixel_t **
XImgAlloc()
X{
X    int			y;
X    pixel_t		**p;
X
X    noerr = 1;
X    if ((p = (pixel_t **) LINT_CAST(Emalloc((unsigned)Xsize * sizeof(pixel_t *)))) == 0)
X	return (pixel_t **) 0;
X
X    for (y = 0; y < Ysize; ++y)
X	p[y] = (pixel_t *) Emalloc((unsigned)Xsize * sizeof (pixel_t));
X
X    if (noerr == 0)
X    {
X	/* Run out of memory; free what we have allocated */
X	for (y = 0; y < Ysize; ++y)
X	{
X	    if (p[y])
X		free((char *) p[y]);
X	}
X	return (pixel_t **) 0;
X    }
X
X    return p;
X}
X
Xvoid
XImgFree(img)
Xstruct SRC	*img;
X{
X    int			y;
X    pixel_t		**p;
X
X    free(img->str);
X    img->str = (char *) 0;
X
X    p = img->pix;
X
X    for (y = 0; y < Ysize; ++y)
X	free((char *) (*p++));
X
X    free((char *) img->pix);
X    img->pix = (pixel_t **) 0;
X}
X
Xvoid
XEfclose(stream)
XFILE	*stream;
X{
X#if	unix
X    if (IsPopen)
X	PCLOSE(stream);
X    else
X#endif	/* unix */
X	FCLOSE(stream);
X}
X
XFILE *
XEfopenR(filename)
Xchar *filename;
X{
X    FILE	*istr;
X#if unix
X    FILE	*popen();
X#endif /* unix */
X
X    DEBUG((Debug, "EfopenR(%s)\n", filename));
X    IsPopen = 0;
X    if ((istr = fopen(filename, RMODE)) != NULL)
X	return istr;
X
X#if	unix
X    if (errno == ENOENT)
X    {
X	char buf[512];
X
X	/* first see if the compressed file exists and is readable */
X	SPRINTF(buf, "%s.Z", filename);
X	if ((istr = fopen(buf, "r")) != NULL)
X	{
X	    /* OK - it's there */
X	    FCLOSE(istr);
X	    SPRINTF(buf, "zcat %s", filename);
X	    DEBUG((Debug, "popen(%s)\n", buf));
X	    if ((istr = popen(buf, "r")) != NULL)
X	    {
X		IsPopen = 1;
X		return istr;
X	    }
X	}
X    }
X#endif	/* unix */
X
X    SPRINTF(ErrBuf, "Can't read file '%s'", filename);
X    error(ERR_SYS);
X    return NULL;
X}
X
XFILE *
XEfopenW(filename)
Xchar	*filename;
X{
X    FILE	*ostr;
X    FILE	*popen();
X
X    DEBUG((Debug, "EfopenW(%s)\n", filename));
X    IsPopen = 0;
X
X#if	unix
X    if (*filename == '|')
X    {
X	++filename;
X
X	if ((ostr = popen(filename, "w")) == NULL)
X	{
X	    SPRINTF(ErrBuf, "Can't run command '%s'", filename);
X	    error(ERR_SYS);
X	}
X	return ostr;
X    }
X#endif	/* unix */
X
X    if ((ostr = fopen(filename, WMODE)) == NULL)
X    {
X	SPRINTF(ErrBuf, "Can't write file '%s'", filename);
X	error(ERR_SYS);
X    }
X    return ostr;
X}
X
X
Xvoid
Xgetpix(filename, imgname)
Xchar	*filename;			/* file name */
Xchar	*imgname;			/* image name */
X{
X    FILE	*fd;
X    int		y,
X		c;
X    struct SRC	*img = (struct SRC *) 0;	/* work buffer */
X    char	*p,
X		*rem;
X
X    if ((fd = EfopenR(filename)) == NULL)
X        return;
X
X    if (imgname == 0 || *imgname == '\0')
X    {
X	imgname = filename;
X
X	/*
X	 * Use the basename of the filename for the image name.
X	 * If this results in a non-valid image name, they'll
X	 * just have to use the $n equivalent. It's not our
X	 * business to go transforming names.
X	 */
X
X	/* find last '/' in string */
X	for (p = rem = imgname; *p; ++p)
X	    if (*p == '/' && p[1] != '\0')
X		rem = p + 1;
X
X	imgname = rem;
X    }
X
X    /* See if the named image already exists */
X    for (c = 0; c < nsrc; c++)
X	if (src[c].str && strcmp(src[c].str, imgname) == 0)
X	{
X	    img = &src[c];
X	    break;
X	}
X
X    if (img == (struct SRC *) 0)
X    {
X	/* Allocate a new image */
X        img = &src[nsrc++];
X
X	if
X	(
X	    (img->pix = ImgAlloc()) == 0
X	    ||
X	    (img->str = (char *) Emalloc((unsigned int) (strlen(imgname)+1))) == 0
X	)
X	    return;
X
X	STRCPY(img->str, imgname);
X    }
X
X    /* Read in the image */
X    for (y = 0; y < Ysize; y++)
X    {
X	long	total = 0;
X	int	count;
X
X	if ((count = fread((char *) img->pix[y], 1, Xsize, fd)) <= 0)
X	{
X	    if (ferror(fd))
X	    {
X		SPRINTF(ErrBuf,
X		    "File '%s' read error (read %ld of %ld bytes)",
X		    filename, total, (long)Xsize * Ysize);
X		error(ERR_SYS);
X		FCLOSE(fd);
X		return;
X	    }
X
X	    SPRINTF(ErrBuf,
X		"File '%s' insufficient data (read %ld of %ld bytes)",
X		filename, total, Xsize * Ysize);
X	    error(0);
X	    return;
X	}
X
X	total += count;
X    }
X
X
X    Efclose(fd);
X}
X
Xvoid
Xputpix(into, str)
Xstruct SRC *into ;       /* work buffer */
Xchar *str ;              /* file name */
X{
X    FILE *fd;
X    int i;
X
X    if ((fd = EfopenW(str)) == NULL)
X	return;
X
X    for (i = 0; i < Ysize; i++)
X	FWRITE((char *) into->pix[i], 1, Xsize, fd);
X
X    Efclose(fd);
X}
X
X
Xvoid
Xshowfiles()
X{
X    int n;
X
X    for (n = 2; n < nsrc; n++)
X	if(src[n].str)
X	{
X	    PRINTF("$%d = %s\n", n - 1, src[n].str);
X	    if (LogStr)
X		FPRINTF(LogStr, "$%d = %s\n", n - 1, src[n].str);
X	}
X}
Funky_Stuff
chmod 0444 io.c || echo "restore of io.c fails"
set `wc -c io.c`;Sum=$1
if test "$Sum" != "5312"
then echo original size 5312, current size $Sum;fi
echo "x - extracting kerterm.c (Text)"
sed 's/^X//' << 'Funky_Stuff' > kerterm.c &&
X/*LINTLIBRARY*/
X
X/*  @(#)kerterm.c 1.2 89/12/11
X *
X *  Popi graphics driver for kermit TERM windows.
X *  written by Frank Crawford - Q.H.Tours.
X *
X *  Popi was originally written by Gerard J. Holzmann - AT&T Bell Labs.
X *  This version is based on the code in his Prentice Hall book,
X *  "Beyond Photography - the digital darkroom," ISBN 0-13-074410-7,
X *  which is copyright (c) 1988 by Bell Telephone Laboratories, Inc. 
X *
X *  Permission is given to distribute these extensions, as long as these
X *  introductory messages are not removed, and no monies are exchanged.
X *
X *  No responsibility is taken for any errors or inaccuracies inherent
X *  either to the comments or the code of this program, but if reported
X *  (see README file) then an attempt will be made to fix them.
X */
X
X
X#include <stdio.h>
X#include <signal.h>
X#include <sys/types.h>
X#include "popi.h"
X
X#define  KER_MAX_X  1023    /* Maximum Kermit X value */
X#define  KER_MAX_Y  779     /* Maximum Kermit Y value */
X#define  PC_MAX_X   640     /* Number of PC X value (EGA Card) */
X#define  PC_MAX_Y   350     /* Number of PC Y value (EGA Card) */
X#define  MAX_GREY   2       /* Max. Greyscale value (Black, Low-int, Hi-int) */
X
Xint thresh[MAX_GREY][BITSPERPIXEL][BITSPERPIXEL] =
X{
X    {        /* Array containing threshold values for low value. */
X      {   0,  64,  16,  80,   4,  68,  20,  84, },
X      {  96,  32, 112,  48, 100,  36, 116,  52, },
X      {  24,  88,   8,  72,  28,  92,  12,  76, },
X      { 120,  56, 104,  40, 124,  60, 108,  44, },
X      {   6,  70,  22,  86,   2,  66,  18,  82, },
X      { 102,  38, 118,  54,  98,  34, 114,  50, },
X      {  30,  94,  14,  78,  26,  90,  10,  74, },
X      { 126,  62, 110,  46, 122,  58, 106,  42, },
X    },
X    {        /* Array containing threshold values for high value. */
X      { 128, 192, 144, 208, 132, 196, 148, 212, },
X      { 224, 160, 240, 176, 228, 164, 244, 180, },
X      { 152, 216, 136, 200, 156, 220, 140, 204, },
X      { 248, 184, 232, 168, 252, 188, 236, 172, },
X      { 134, 198, 150, 214, 130, 194, 146, 210, },
X      { 230, 166, 246, 182, 226, 162, 242, 178, },
X      { 158, 222, 142, 206, 154, 218, 138, 202, },
X      { 254, 190, 238, 174, 250, 186, 234, 170, },
X    },
X};
X
X/*  There are ten exportable routines used by the popi program.
X *
X *  These are:
X *
X *  disp_init(argc, argv)    - called from main at the start.
X *  disp_finish()            - called from main prior to exit.
X *  disp_imgstart()          - called prior to drawing an image.
X *  disp_imgend()            - called after drawing an image.
X *  disp_putline(line, y)    - to draw an image scanline.
X *  disp_getchar()           - to get the next character typed.
X *  disp_ungetc(c)           - put back the last character typed.
X *  disp_prompt()            - display popi prompt and clear input buffer.
X *  disp_error(errtype)      - display error message.
X *  disp_percentdone(n)      - display percentage value of conversion.
X */
X
X/*ARGSUSED*/
Xvoid
Xdisp_init(argc,argv)
Xint argc;
Xchar *argv[];
X{
X}
X
Xvoid
Xdisp_finish()
X{
X}
X
Xvoid
Xdisp_intr(signal)
Xint signal;
X{
X    disp_imgend();
X    exit(signal);
X}
X
Xvoid
Xdisp_imgstart()
X{
X    (void) signal(SIGINT, disp_intr);
X    putchar('\033');
X    putchar('\f');
X}
X
Xvoid
Xdisp_imgend()
X{
X    char ch;
X
X    putchar('\033');
X    putchar('[');
X    putchar('0');
X    putchar('m');
X    PRINTF("\037\n\n\007Hit return when ready:");
X    fflush(stdout);
X    while (read(1, &ch, 1) == 1 && ch != '\n')	/* Because of inconsistent use */
X	;
X    putchar('\033');
X    putchar('[');
X    putchar('?');
X    putchar('3');
X    putchar('8');
X    putchar('l');
X    fflush(stdout);
X    (void) signal(SIGINT, SIG_DFL);
X}
X
Xstatic void
Xcoord(x, y, repeat)
Xint x, y;
Xint repeat;
X{
X    /*
X     * This function goes to a lot of effort to optimes the number of
X     * characters sent down the line.
X     */
X    int hi_x, lo_x, hi_y, lo_y;
X    static int sav_x = -1, sav_y = -1;
X
X    y = KER_MAX_Y - y;	/* To invert picture */
X    hi_x = (x / 32);
X    lo_x = (x % 32);
X    hi_y = (y / 32);
X    lo_y = (y % 32);
X    if (!repeat || y != sav_y)
X    {
X	putchar(hi_y + 0x20);
X	putchar(lo_y + 0x60);
X	putchar(hi_x + 0x20);
X    }
X    else if (hi_x != (sav_x / 32))
X    {
X	putchar(lo_y + 0x60);
X	putchar(hi_x + 0x20);
X    }
X    putchar(lo_x + 0x40);
X    sav_x = x;
X    sav_y = y;
X}
X
Xvoid
Xdisp_putline(line,y)                     /* Output scanline y. */
Xpixel_t *line;
Xint y;
X{
X    int x;
X    int real_x, real_y;
X    int repeat, level;
X    static old_level = 0;
X
X    repeat = 0;
X    /*
X     * Calculate the real pixel location to handle the grey-scale threshold
X     * values.
X     */
X    real_y = (y * PC_MAX_Y) / (KER_MAX_Y + 1);
X    putchar('\034');
X    for (x = 0; x < Xsize; x++, line++)
X    {
X      /* See above */
X      real_x = (x * PC_MAX_X) / (KER_MAX_X + 1);
X      for (level = 0; level < MAX_GREY; level++)
X          if (*line < thresh[level][real_y % BITSPERPIXEL][real_x % BITSPERPIXEL])
X              break;
X	if (level != old_level)
X	{
X	    if (level != 0)
X	    {
X		putchar('\033');
X		putchar('[');
X		putchar((level == 1) ? '0' : '1');
X		putchar('m');
X	    }
X	    old_level = level;
X	}
X	if (level != 0)
X	    coord(x, y, repeat++);
X    }
X    putchar('\n');
X}
X
X
Xdisp_getchar()          /* Get next user typed character. */
X{
X    return(getchar());
X}
X
X
Xvoid
Xdisp_ungetc(c)         /* Put back the last character typed. */
Xchar c ;
X{
X    UNGETC(c, stdin);
X}
X
X
X
Xdisp_prompt()         /* Display popi prompt and clear input line. */
X{
X    PRINTF("-> ");
X    return 3;
X}
X
X
Xvoid
Xdisp_error(errtype, pos)         /* Display error message. */
Xint errtype, pos ;
X{
X    extern int  errno;
X    extern char *sys_errlist[];
X
X    if (errtype & ERR_PARSE)
X    {
X        int     i;
X 
X        for (i=1; i < pos; ++i)
X            PUTC('-', stderr);
X        PUTC('^', stderr);
X        PUTC('\n', stderr);
X    }
X 
X    FPRINTF(stderr, "%s\n", ErrBuf);
X    /* we assume errno hasn't been reset by the preceding output */
X    if (errtype & ERR_SYS)
X        FPRINTF(stderr, "\t(%s)\n", sys_errlist[errno]);
X}
X
Xvoid
Xdisp_percentdone(percent)
Xint	percent;
X{
X    static int	lastpercent = 100;
X
X    if (!Verbose)
X	return;
X    if (percent == 100)
X    {
X	printf("\r    \n");
X	return;
X    }
X    if (percent != lastpercent && percent % 5 == 0)
X    {
X	printf("\r%2d%% ", percent);
X	fflush(stdout);
X	lastpercent = percent;
X    }
X}
Funky_Stuff
chmod 0444 kerterm.c || echo "restore of kerterm.c fails"
set `wc -c kerterm.c`;Sum=$1
if test "$Sum" != "6329"
then echo original size 6329, current size $Sum;fi
echo "x - extracting main.c (Text)"
sed 's/^X//' << 'Funky_Stuff' > main.c &&
X/*  @(#)main.c 1.11 89/12/12
X *
X *  Main routine and declarations used by the popi program.
X *
X *  Popi was originally written by Gerard J. Holzmann - AT&T Bell Labs.
X *  This version is based on the code in his Prentice Hall book,
X *  "Beyond Photography - the digital darkroom," ISBN 0-13-074410-7,
X *  which is copyright (c) 1988 by Bell Telephone Laboratories, Inc. 
X *
X *  Permission is given to distribute these extensions, as long as these
X *  introductory messages are not removed, and no monies are exchanged.
X *
X *  No responsibility is taken for any errors or inaccuracies inherent
X *  either to the comments or the code of this program, but if reported
X *  (see README file) then an attempt will be made to fix them.
X */
X
X
X#include <stdio.h>
X#include <ctype.h>
X#include "popi.h"
X#include "patchlevel.h"
X
X/* prototypes for local functions */
X
Xbool	do_parse P((void));
Xvoid	get_options P((char **));
Xvoid	Usage P((int));
Xint	main P((int, char **));
X
Xstruct SRC
X	src[MAXIMG];		/* array of images */
Xshort	CUROLD = 0;		/* index of "old" image */
Xshort	CURNEW = 1;		/* index of "new" image */
Xint	noerr = 1;
Xint	lexval;			/* value of numerical token */
Xint	Xsize = DEF_X,		/* image width */
X	Ysize = DEF_Y,		/* image height */
X	Zsize = DEF_ZSIZE;	/* no. brightness levels */
Xpixel_t	Zmax = DEF_ZSIZE - 1;	/* max brightness level */
Xchar	text[512];		/* value of string token */
Xchar	*ProgName,		/* program name (for err messages) */
X        *LogFile = "popi.log";  /* Name of log file */
XFILE	*Debug = NULL,		/* debugging output stream */
X        *LogStr = NULL;         /* logging output stream */
Xint	disp_active = 1,	/* so we can turn off the display */
X	Truncate = 0,		/* Truncate assignments instead of wrapping. */
X	Verbose = 0;		/* be chatty */
Xchar	geometry[MAXLINE];	/* X11 geometry information. */
Xchar	x11_display[MAXLINE];	/* X11 display information. */
Xint	iconic = 0;		/* Set if the window is in an iconic state. */
X
X#if       SEQPAR
Xint     ncpus = 1;              /* default is single-tasking */
X#endif /* SEQPAR */
X
Xstatic char *UsageMsg[] =
X{
X    "valid options:",
X    "\t-xWidth\t\tspecify image width (number pixels)",
X    "\t-yHeight\tspecify image height (number scanlines)",
X    "\t-a[+-]\t\tturn auto-display on or off",
X    "\t-r[+-]\t\tturn range checking on or off",
X    (char *) 0
X};
X
Xvoid
XPrStrs(msg)
Xchar	*msg[];
X{
X    char	**p;
X
X    p = msg;
X    for (p = msg; *p; ++p)
X	FPRINTF(stderr, "%s\n", *p);
X}
X
Xstatic void
XUsage(status)
Xint	status;
X{
X    FPRINTF(stderr, "Usage: %s [options] [image-files]\n", ProgName);
X    PrStrs(UsageMsg);
X	/* Also need a driver-specific usage message appended */
X    exit(status);
X}
X
Xvoid
Xversion()
X{
X    FPRINTF(stderr, "%s: version 2.1.%1d\n", ProgName, PATCHLEVEL);
X}
X
Xstatic void
Xget_options(argv)           /* read command line options. */
Xchar *argv[];
X{
X    for (ProgName = *argv++; *argv && **argv == '-'; ++argv)
X    {
X        switch (*++*argv)
X        {
X            case 'x':
X                Xsize = atoi(++*argv);
X                break;
X
X            case 'y':
X                Ysize = atoi(++*argv);
X                break;
X
X            case 'z':
X                Zsize = atoi(++*argv);
X                Zmax = (pixel_t) (Zsize - 1);
X                break;
X
X            case 'D':
X                if (*++*argv)
X                {
X                    if ((Debug = fopen(*argv, "w")) == NULL)
X                    {
X                        SPRINTF(ErrBuf,
X                            "Can't open debug file '%s' - using stderr",
X                            *argv);
X                        error(ERR_SYS);
X                        Debug = stderr;
X                    }
X                }    
X                else
X                    Debug = stderr;
X                setbuf(Debug, NULL);  /**/
X                break;
X
X            case 'l':   /* log all commands */
X              if (*++*argv)
X                  LogFile = *argv;
X              OpenLog();
X              break;
X
X            case 'p':   /* No. cpus to use in parallel */
X              /* Still recognise the option on other machines,
X               * so scripts can use this option portably.
X               */
X
X#if       SEQPAR
X              if (*++*argv)
X              {
X                  ncpus = atoi(*argv);
X                  if (ncpus >= cpus_online())
X                      ncpus = cpus_online() - 1;
X                  if (ncpus < 0)
X                      ncpus = 0;
X              }
X              else
X                  ncpus = cpus_online() - 1;
X#endif /* SEQPAR */
X
X              break;
X
X            case 'd':   /* x11 display information. */
X		++argv;
X		STRCPY(x11_display,*argv);
X		break;
X
X	    case 'g':   /* x11 geometry information. */
X		++argv;
X		STRCPY(geometry,*argv);
X		break;
X
X	    case 'i':   /* start window iconically. */
X		iconic = 1;
X		break;
X
X	    case 'r':   /* range checking */
X                if (*++*argv == '-')
X                    RangeCheck = 0;
X                else
X                    RangeCheck = 1;
X                break;
X
X            case 'a':   /* auto-display */
X                if (*++*argv == '+')
X                    disp_active = 1;
X                else
X                    disp_active = 0;
X                break;
X
X	    case 'v':	/* verbose */
X		if (*++*argv == '-')
X		    Verbose = 0;
X		else
X		    ++Verbose;
X		break;
X
X            case 'V':   /* print version number. */
X		version();
X		exit(0);
X		break;
X
X	    case '?':	/* Print usage message */
X	    	Usage(0);
X		/* NOTREACHED */
X
X	    /* Note: no error on default because drivers may
X	     * interpret other options.
X	     */
X	    default:
X		--*argv;	/* reset for disp_init() */
X        }
X    }
X
X    src[CUROLD].pix = ImgAlloc();
X    src[CUROLD].str = "old";
X    src[CURNEW].pix = ImgAlloc();
X    src[CURNEW].str = "new";
X
X    for (; *argv; ++argv)
X        getpix(*argv, (char *) 0);
X}
X
X
X/*
X * Parse	= # special
X *		| '?'				help
X *		| 'q'				quit
X */
Xstatic bool
Xdo_parse()
X{
X    extern int lat ;     /* look ahead token */
X
X    /* display popi prompt and clear input line. Returns length of popi prompt. */
X    CharPos = disp_prompt();
X
X    if (LogStr)
X    {
X	FPRINTF(LogStr, "-> ");
X	FFLUSH(LogStr);
X    }
X
X    lex();
X
X    switch (lat)
X    {
X	case '#':
X	    special();
X	    break;
X
X	case '?':
X	    help();
X	    Skip();
X	    break;
X
X	case 'q':
X	    return FALSE;
X
X	case '\n':
X	    break;
X
X	default:
X	    transform();
X	    if (noerr)
X		run();
X	    break;
X    }
X    assert(lat == '\n');
X    return TRUE;
X}
X
X
X/*
X *	We deliberately don't exit on error here.
X *	The user may have some picture that has taken ages to develop.
X *	If we run out of memory, they have a chance to save the
X *	image and exit themselves, which they should do as soon
X *	as possible.
X */
X
Xchar *
XEmalloc(n)
Xunsigned int n;
X{
X    char	*try;
X    static unsigned long
X		TotalAllocated = 0L;
X
X    if ((try = malloc(n)) == NULL)
X    {
X	SPRINTF(ErrBuf,
X	    "Allocate %u bytes failed (total malloc=%lx)",
X	    n, TotalAllocated);
X	error(ERR_SYS);
X    }
X    TotalAllocated += n;
X    return try;
X}
X
Xmain(argc,argv)
Xint argc;
Xchar **argv;
X{
X    get_options(argv) ;          /* read the command line options. */
X    disp_init(argc, argv);
X
X#if       SEQPAR
X    m_set_procs(ncpus);
X#endif /* SEQPAR */
X
X    do
X	noerr = TRUE;
X    while (do_parse());
X
X    disp_finish();
X
X	/* Some compilers don't get the exit status right when
X	 * you return from main()
X	 */
X    exit(0);
X    return 0;	/* shut up warning messages from some compilers */
X}
Funky_Stuff
chmod 0444 main.c || echo "restore of main.c fails"
set `wc -c main.c`;Sum=$1
if test "$Sum" != "7419"
then echo original size 7419, current size $Sum;fi
echo "x - extracting mgr.c (Text)"
sed 's/^X//' << 'Funky_Stuff' > mgr.c &&
X/*LINTLIBRARY*/
X
X/*  @(#)mgr.c 1.8 89/12/11
X *
X *  MGR dependent graphics routines used by popi.
X *  written by Rich Burridge - Sun Microsystems.
X *
X *  Popi was originally written by Gerard J. Holzmann - AT&T Bell Labs.
X *  This version is based on the code in his Prentice Hall book,
X *  "Beyond Photography - the digital darkroom," ISBN 0-13-074410-7,
X *  which is copyright (c) 1988 by Bell Telephone Laboratories, Inc. 
X *
X *  Permission is given to distribute these extensions, as long as these
X *  introductory messages are not removed, and no monies are exchanged.
X *
X *  No responsibility is taken for any errors or inaccuracies inherent
X *  either to the comments or the code of this program, but if reported
X *  (see README file) then an attempt will be made to fix them.
X */
X
X#include "dump.h"
X#include "term.h"
X#include "popi.h"
X#include "graphics.h"
X#include <signal.h>
X#include <sys/types.h>
X#include <sys/time.h>
X
X#define  B_FONT       1    /* Font descriptors. */
X#define  N_FONT       2
X
X#define  ICONIC       0    /* States that the popi display can be in. */
X#define  OPEN         1
X
X#define  PR_ICON      1    /* Descriptor for closed icon image. */
X#define  PR_SCAN      2    /* Descriptor for current popi scan line. */
X
X#define  BOLD_FONT    "cour7x14b"
X#define  NORMAL_FONT  "cour7x14r"
X
X#define  ICONHEIGHT   64   /* Height of the popi icon. */
X#define  ICONWIDTH    64   /* Width of the popi icon. */
X
Xchar fontname[MAXLINE] ;   /* Full pathname of each font. */
X
Xint local_mode;            /* Used by load_icon for correct line mode. */
Xint mgr_infd ;             /* MGR input connection file descriptor. */
Xint mgr_outfd ;            /* MGR output connection file descriptor. */
X
Xshort icon_image[] = {
X#include "popi.icon"
X} ;
X
X#ifdef NO_43SELECT
Xint fullmask ;             /* Full mask of file descriptors to check on. */
Xint readmask ;             /* Readmask used in select call. */
X#else
Xfd_set fullmask ;          /* Full mask of file descriptors to check on. */
Xfd_set readmask ;          /* Readmask used in select call. */
X#endif /* NO_43SELECT */
X
X
XSIGRET
Xclean(code)
Xint code ;
X{
X  m_bitdestroy(1) ;
X  m_pop() ;
X  m_ttyreset() ;
X  m_clear() ;
X  exit(code) ;
X}
X
X
Xcleanup()                   /* Cleanup before exiting. */
X{
X  clean(0) ;
X}
X
X
Xclose_frame()
X{
X  reshape(ICONIC) ;
X  m_clearmode(M_ACTIVATE) ;
X  iconic = 1 ;
X}
X
X
Xdraw_scanline(line, y)       /* Display image scanline on the screen. */
Xunsigned char *line ;
Xint y ;
X{
X  int fd, size ;
X
X  halftone(line, y) ;
X
X  IOCTL(mgr_outfd, TIOCLGET, &local_mode) ;
X  local_mode |= LLITOUT ;
X  IOCTL(mgr_outfd, TIOCLSET, &local_mode) ;
X
X  size = (Xsize / 8) + 1 ;
X  m_bitldto(Xsize, 1, 0, 0, PR_SCAN, size) ;
X  m_flush() ;
X  WRITE(mgr_outfd, mptr, size) ;
X
X  local_mode &= ~LLITOUT ;
X  IOCTL(mgr_outfd, TIOCLSET, &local_mode) ;
X
X  m_bitcopyto(0, y+100, Xsize, 1, 0, 0, 0, PR_SCAN) ;
X}
X
X
Xdrawarea(x, y, width, height, op)
Xint x, y, width, height ;
Xenum op_type op ;
X{
X  m_func(ops[(int) op]) ;
Funky_Stuff
echo "End of part 2"
echo "File mgr.c is continued in part 3"
echo "3" > s2_seq_.tmp
exit 0