/* dispmacros.h --- display macros for niftyterm
 *
 * Copyright 1989, Chris Newman
 * All Rights Reserved
 * Permission is granted ot copy, modify, and use this as long
 * as this notice remains intact.  This is a nifty program.
 *
 * $Author: ppessi $ $Revision: 2.0 $ $Date: 1993/11/15 03:30:07 $
 */

#define MAXWIDTH	132
#define	MINWIDTH	40
#define MAXHEIGHT	75
#define	MINHEIGHT	2

/* This data structure should not need changing for different displays
 * format of buffers:
 * disp.sbuf -- x*(y+1) array of line styles
 *	first byte in disp.sbuf line: OR of all styles on line
 *		-- if 0, then no styles, if -1, unused
 */
extern struct nifty_display {
    int	    curx;			/* cursor location  [0,winwidth),[0,winwinheight) */
    int	    cury;
    int	    savex;			/* save of cursor position */
    int	    savey;
    int	    winwidth;			/* window size: columns, rows */
    int	    winheight;
    int	    maxwidth;			/* width of the buffer */
    int	    maxheight;			/* height of the buffer */
    int	    bufwidth;			/* width of buffer (maxwidth+1) */
    int	    scrolltop;			/* top of scrolling region */
    int	    scrollbot;			/* bottom of scrolling region */
    int	    scrollskip;			/* amount to jump scroll */
    int	    scrolldefault;		/* default scroll skip */
    short   style;			/* current display style */
    short   savestyle;			/* save the display style */
    int	    invert;			/* invert the screen */
    int	    insert;			/* insert mode */
    int	    origin;			/* origin mode -- if 1, origin at scrolltop */
    int	    wrap;			/* 0=stop at margin, 1=wrap at margin */
    int	    visual;			/* 0=underline cursor, 1=block cursor,
						 2 = invisible cursor */
    int     blink;                      /* 0=no blink, 1=blinking cursor */
    char    *plines[MAXHEIGHT];		/* array of line pointers (faster scrolling) */
    short   *pstyles[MAXHEIGHT];	/* array of style pointers (faster scrolling) */
    char    *buf;			/* malloc text buffer */
    short   *sbuf;			/* malloc styles buffer */
    char    *tabstops;			/* malloc flag buffer */
} disp;

/* cursor visual attributes */
#define CUR_UNDERLINE	0x00
#define CUR_BLOCK	0x01
#define CUR_INVISIBLE	0x02
#define CUR_BOX		0x04
#define CUR_NOBLINK     0x00
#define CUR_BLINK       0x01

/* attributes */
#define	UNDERLINE	(0x0001)
#define	BOLD		(0x0002)
#define	ITALIC		(0x0004)
#define	DOUBLE1		(0x0008)
#define	DOUBLE2		(0x0010)
#define	ALTERNATE	(0x0020)
#define	INVERSE		(0x0040)
#define	FLASH		(0x0080)
#define	BLANK		(0x0100)
#define	HALFBRITE	(0x0200)
#define	DOUBLE_MASK	(DOUBLE1 | DOUBLE2)

/* marcos to access data structure */
#define	STYLEFLAG(y)	(disp.pstyles[y][disp.maxwidth])
#define	LINELENST(y)	(disp.plines[y][disp.maxwidth])
#define	LINELEN(y)	((unsigned char) LINELENST(y))
#define	STYLELINE(y)	(disp.pstyles[y])
#define	TEXTLINE(y)	(disp.plines[y])
#define	TEXTPOS(x, y)	(disp.plines[y][x])
#define	STYLEPOS(x, y)	(disp.pstyles[y][x])

/* macros to operate on the display */
#define	NEWLINE()	if (++disp.cury > disp.scrollbot) {disp.cury-=disp.scrollskip; dsscroll(disp.scrolltop, disp.scrollbot - disp.scrolltop + 1, disp.scrollskip);}

#define DSTEST(c, style)  /* fill screen with character c, style s */\
{									    \
    register int tx, ty;						    \
    for	(ty = 0; ty < disp.winheight; ty++) {				    \
	LINELENST(ty) = disp.winwidth-1;				    \
	STYLEFLAG(ty) = style;						    \
	for (tx	= 0; tx	< disp.winwidth; tx++)				    \
	    TEXTPOS(tx,	ty) = (c), STYLEPOS(tx,	ty) = (style);		    \
    }									    \
}

#define	DSCLEAR(x,y,x1,y1)	/* quickly clear out the interal storage */\
{									    \
    register int tempx,	tempy;						    \
    int	linelen;							    \
    for	(tempy = y; tempy <= y1; tempy++) {				    \
	if (x >	(linelen = LINELEN(tempy)))				    \
	    continue;							    \
	if (x1 > linelen) {						    \
	    LINELENST(tempy) = linelen = x;				    \
	} else								    \
	    for	(tempx = x; tempx <= x1; tempx++)			    \
		TEXTPOS(tempx, tempy) =	' ', STYLEPOS(tempx, tempy) = 0;    \
	STYLEFLAG(tempy) &= DOUBLE_MASK;				    \
	for (tempx = 0;	tempx <= linelen;tempx++)			    \
	    STYLEFLAG(tempy) |=	STYLEPOS(tempx,	tempy);			    \
    }									    \
}

/* clip cursor position, clip lines, and recalculate styles */
#define	DSRESIZE() {\
    register int x, y;\
    int	linelen;\
    SLIMITCK(disp.curx,	disp.winwidth);\
    SLIMITCK(disp.cury,	disp.winheight);\
    for (y = 0; y < disp.winheight; y++) {\
	if (disp.winwidth < (linelen=LINELEN(y)))\
	LINELENST(y) = linelen = disp.winwidth;\
	for (style = STYLEFLAG(y) & DOUBLE_MASK, x = 0;\
	x < disp.winwidth && x < linelen; x++)\
	style |= STYLEPOS(x,y);\
	STYLEFLAG(y) = style;\
    }\
    SLIMITCK(disp.scrollbot,disp.winheight);\
    if (disp.scrolltop >= disp.scrollbot-1)\
    disp.scrolltop = 0;\
}

#define	DSSCROLL(y, amount, numlines)\
if(ABS(amount)<(numlines)) {\
char *templ;\
short *templs;\
int i, maxy;\
if(amount>0) {\
for(i=y,maxy=y+numlines-amount;i<maxy;i++){\
templ=disp.plines[i],templs=disp.pstyles[i];\
disp.plines[i]=disp.plines[i+amount];\
disp.pstyles[i]=disp.pstyles[i+amount];\
disp.plines[i+amount]=templ,disp.pstyles[i+amount]=templs;\
}\
}\
else {\
for(i=y+numlines-1,maxy=y-amount;i>=maxy;i--){\
templ=disp.plines[i],templs=disp.pstyles[i];\
disp.plines[i]=disp.plines[i+amount];\
disp.pstyles[i]=disp.pstyles[i+amount];\
disp.plines[i+amount]=templ,disp.pstyles[i+amount]=templs;\
}\
}\
}

#define	DSEMPTYLINE(top, bottom)    /* empty lines from top to bottom-1 */\
{									    \
    register int i;							    \
    for	(i = top; i < bottom; i++)					    \
	LINELENST(i) = STYLEFLAG(i) = 0;				    \
}


