/*LINTLIBRARY*/

/*  @(#)next.m 1.7 89/12/11
 *
 *  Popi device driver for a next machine
 *  Written by Joe Freeman.
 *
 *  Popi was originally written by Gerard J. Holzmann - AT&T Bell Labs.
 *  This version is based on the code in his Prentice Hall book,
 *  "Beyond Photography - the digital darkroom," ISBN 0-13-074410-7,
 *  which is copyright (c) 1988 by Bell Telephone Laboratories, Inc. 
 *
 *  Permission is given to distribute these extensions, as long as these
 *  introductory messages are not removed, and no monies are exchanged.
 *
 *  No responsibility is taken for any errors or inaccuracies inherent
 *  either to the comments or the code of this program, but if reported
 *  (see README file) then an attempt will be made to fix them.
 */

#include "popi.h"
#import "appkit/appkit.h"	/* lazy tsk tsk */

/*  There are ten exportable routines used by the popi program.
 *
 *  These are:
 *
 *  disp_init(argc, argv)    - called from main at the start.
 *  disp_finish()            - called from main prior to exit.
 *  disp_imgstart()          - called prior to drawing an image.
 *  disp_imgend()            - called after drawing an image.
 *  disp_putline(line, y)    - to draw an image scanline.
 *  disp_getchar()           - to get the next character typed.
 *  disp_ungetc(c)           - put back the last character typed.
 *  disp_prompt()            - display popi prompt and clear input buffer.
 *  disp_error(errtype)      - display error message.
 *  disp_percentdone(n)      - display percentage value of conversion.
 */

#define  RES  8
int dither[RES][RES] = {        /* dither matrix */
  {   0, 128,  32, 160,   8, 136,  40, 168, },
  { 192,  64, 224,  96, 200,  72, 232, 104, },
  {  48, 176,  16, 144,  56, 184,  24, 152, },
  { 240, 112, 208,  80, 248, 120, 216,  88, },
  {  12, 140,  44, 172,   4, 132,  36, 164, },
  { 204,  76, 236, 108, 196,  68, 228, 100, },
  {  60, 188,  28, 156,  52, 180,  20, 148, },
  { 252, 124, 220,  92, 244, 116, 212,  84, },
} ;

id	NXApp;
id	drawWindow,percentWindow;

#define	PERCENTHEIGHT	50
#define	PERCENTWIDTH	120
#define	LOGHEIGHT	250
#define	LOGWIDTH	200
#define	DRAWBASEX		250
#define	DRAWBASEY 	250

/*ARGSUSED*/
void
disp_init(argc,argv)           /* called from main at the atart. */
int argc;
char *argv[];
{
	NXRect	bound;
	NXApp = [Application new];
	[NXApp setAppName:"popi"];
	bound.origin.x = DRAWBASEX;
	bound.origin.y = DRAWBASEY;
	bound.size.width = Xsize;  bound.size.height = Ysize;
	drawWindow = [Window newContent:&bound
						style:NX_TITLEDSTYLE
						backing: NX_RETAINED
						buttonMask: NX_MINIATURIZEBUTTONMASK
						defer : NO];
	[[drawWindow contentView] setFlip:YES];	/* start at top */
	[drawWindow orderFront:nil];
	[drawWindow setTitle:"popi image window"];
	[drawWindow display];
	bound.origin.x = DRAWBASEX - PERCENTWIDTH;
	bound.origin.y = DRAWBASEY + Ysize - PERCENTHEIGHT;
	bound.size.width = PERCENTWIDTH; bound.size.height = PERCENTHEIGHT;
	percentWindow = [Panel newContent:&bound
						style:NX_TITLEDSTYLE
						backing: NX_RETAINED
						buttonMask: 0
						defer: NO];
	[percentWindow setTitle:"percent done"];
	bound.origin.x = 40.0; bound.origin.y = 350;
	bound.size.width = LOGWIDTH; bound.size.height = LOGHEIGHT;
	[percentWindow display];
	bound.origin.x = 0.0; bound.origin.y = DRAWBASEY;
	bound.size.width = DRAWBASEX ;  bound.size.height = Ysize - PERCENTHEIGHT;
	NXPing();
}


void
disp_finish()                  /* called from main prior to exit. */
{
	[drawWindow free];
	[percentWindow free];
	[NXApp free];
}


void
disp_imgstart()                /* called prior to drawing an image. */
{
}


void
disp_imgend()                  /* called after drawing an image. */
{
	[drawWindow flushWindow];
	NXPing();
}


void
disp_putline(line, y)		/* called to draw image scanline y. */
pixel_t *line;
int y;
{
	NXRect	theRect;
	[[drawWindow contentView] lockFocus];
	PSgsave();
	theRect.origin.x = 0.0;
	theRect.origin.y = (float)y;
	theRect.size.width = (float)Xsize;
	theRect.size.height = (float)1.0;
	NXImageBitmap(&theRect, Xsize, 1.0, 
					8, 1, NX_PLANAR, NX_MONOTONICMASK, 
					line, NULL,NULL, NULL, NULL);
 	PSgrestore();
	[[drawWindow contentView] unlockFocus];
}


disp_getchar()                 /* get next user typed character. */
{
    return(getchar());
}


/*ARGSUSED*/
void
disp_ungetc(c)                 /* put back the last character typed. */
char c;
{
    UNGETC(c, stdin);
}


disp_prompt()                  /* display popi prompt. */
{
    char	*prompt = "-> ";

    PRINTF(prompt);
    return sizeof prompt - 1;
}


void
disp_error(errtype, pos)            /* display error message. */
int	errtype,
	pos;
{
    extern int  errno;
    extern char *sys_errlist[];

    if (errtype & ERR_PARSE)
    {
        int     i;
 
        for (i=1; i < pos; ++i)
            PUTC('-', stderr);
        PUTC('^', stderr);
        PUTC('\n', stderr);
    }
 
    FPRINTF(stderr, "%s\n", ErrBuf);
    /* we assume errno hasn't been reset by the preceding output */
    if (errtype & ERR_SYS)
        FPRINTF(stderr, "\t(%s)\n", sys_errlist[errno]);
}

void
disp_percentdone(percent)
int	percent;
{
    static	int	lastpercent = 100;
    static	NXRect	bound;

    if (!Verbose)
	return;
    if (percent == 100)
    {
    	[percentWindow orderOut:nil];
	return;
    }
    if ((percent == 0) && (lastpercent != 0))
    {
    	[[percentWindow  contentView] lockFocus];
    	[[percentWindow  contentView] getBounds:&bound];
	NXDrawGrayBezel( &bound, &bound);
    	[[percentWindow contentView] unlockFocus];
    	[percentWindow orderFront:nil];
	NXPing();
	bound.origin.x = bound.origin.y = 10.0;
	bound.size.height = PERCENTHEIGHT - (2.0 * 10.0);
	lastpercent = percent;
    }
    if (percent != lastpercent && percent % 5 == 0)
    {
	[[percentWindow contentView] lockFocus];
	bound.size.width = (float)percent;
	NXDrawButton(&bound,&bound);
	[[percentWindow contentView] unlockFocus];
	NXPing();
	lastpercent = percent;
    }
}
