RCS_ID_C="$Id: amigadisplay.c,v 3.2 1994/01/08 08:51:57 ppessi Exp $";
/*
 * amigadisplay.c --- Rastport drawing routines for napsaterm
 *
 * Author: ppessi <Pekka.Pessi@hut.fi>
 *
 * Copyright © 1993 Pekka Pessi
 *
 * Last modified: Sat Jan  8 07:42:35 1994 ppessi
 *
 * Copyright 1989, Chris Newman.  Changes Copyright 1989, Todd Williamson.
 * All Rights Reserved
 * Permission is granted to copy, modify, and use this as long
 * as this notice remains intact.  This is a nifty program.
 *
 * Parts of this program were swiped from Joe Keane's jterm, and other parts
 * were swiped from ITC's h19 terminal.
 *
 * DISCLAIMER: the author (and maintainer) of this program is not responsible
 * for any damage or other problems caused by it.
 *
 * $Author: ppessi $ $Revision: 3.2 $ $Date: 1994/01/08 08:51:57 $
 */

#include <assert.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include "nifty.h"
#include "amiga.h"
#include "display.h"
#include "dispmacros.h"
#include "napsaprefs.h"
#include "nio.h"

#include "wimp.h"

#include <graphics/gfxmacros.h>
/* imported globals */
extern int vt100_yucky_wrap_mode;   /* hack to do v100's wrap mode */

#define INVERT 0x50		/* Useful MinTerms  */
#define WHITE  0x00
#define BLACK  0xff

#define DEFDRMD JAM2		/* The default drawing mode */

/* Blitter call made to entire display.  Pass in the MinTerm */
#define	INVERTALL(mode) \
    BltBitMapRastPort(rp->BitMap, 0, 0, rp, POSX(0), POSY(0),\
		      wm.x, wm.y, (mode))

static void wmputs(int x, int y, unsigned char *stng, int style);

struct RastPort *rp = NULL;     /* Drawing rastport */
struct RastPort myrp;		/* A copy of Windows rastport */

/* current flash mode: 0 = not inverse */
static int flashmode = 0;		

/* Output string with default style */
static void putstring(short x, short y, const char *string, int len) 
{ 
    if (disp.invert) 
        SetDrMd(rp, DEFDRMD | INVERSVID); 

    Move(rp, STYLEFLAG(y) & DOUBLE_MASK ? POSX(x) << 1 : POSX(x), 
        POSY(y) + wm.font.b); 

    if (np.national == NAT_7BIT) {
	UBYTE shown[MAXWIDTH + 1];
	long cnt = 0;
	for (; cnt < len; )
	    shown[cnt++] = national_show[(UBYTE)*string++];
	Text(rp, shown, len);
    } else 
	Text(rp, (UBYTE *)string, len);

    if (disp.invert)
        SetDrMd(rp, DEFDRMD); 
}

/* this macro outputs a string with styles */
static void styleput(short x, short y, 
		     const char *string, short len, int style)
{ 
    int	sputswflag = (STYLEFLAG(y) & DOUBLE_MASK) != 0; 

    putstring(x, y, string, len); 
    if (XOR((style) & INVERSE,(style) &	FLASH && flashmode)) { 
	BltBitMapRastPort(rp->BitMap, 0, 0, rp, 
			  POSX(x << sputswflag), POSY(y), 
	                  wm.font.w * len << sputswflag, 
			  wm.font.h, INVERT); 
    }
}

/* 
 * Set appropriate font
 */
#define SETFONT(style, line) \
  setfont(rp, ((style) | (STYLEFLAG(line) & DOUBLE_MASK)) & ATTRIB_MASK)

void dssetfont(register short style, register int line)
{
  /* Do only when mapped */
  if (rp)
    SETFONT(style, line);
}


static int cursormode = 0;	/* current cursor state 1=visible */

/*
 * cursor display routine
 */
void dscursoron(void)
{
    if (rp) {
	int wflag = (STYLEFLAG(disp.cury) & DOUBLE_MASK) != 0;
	if (!cursormode) {
	    cursormode = 1;
	    if (disp.visual == CUR_BLOCK) {
		BltBitMapRastPort(rp->BitMap, 1, 1, rp, 
				  POSX(disp.curx << wflag),
				  POSY(disp.cury), 
				  wm.font.w << wflag, wm.font.h, INVERT);
	    }
	    else if (disp.visual == CUR_UNDERLINE) {
		BltBitMapRastPort(rp->BitMap, 1, 1, rp, 
				  POSX(disp.curx << wflag),
				  POSY(disp.cury) + wm.font.b + 1, 
				  wm.font.w << wflag, 1, INVERT);
	    }
	}
    }
}

void dscursoroff(void)
{
    if (rp) {
	int wflag = (STYLEFLAG(disp.cury) & DOUBLE_MASK) != 0;

	if (isSelection()) 
	    killSelection();
	if (cursormode) {
	    cursormode = 0;
	    if (disp.visual == CUR_BLOCK) {
		BltBitMapRastPort(rp->BitMap, 1, 1, rp, 
				  POSX(disp.curx << wflag),
				  POSY(disp.cury), 
				  wm.font.w << wflag, 
				  wm.font.h, 
				  INVERT);
	    } else if (disp.visual == CUR_UNDERLINE) {
		BltBitMapRastPort(rp->BitMap, 1, 1, rp, 
				  POSX(disp.curx << wflag),
				  POSY(disp.cury) + wm.font.b + 1, 
				  wm.font.w << wflag, 
				  1, 
				  INVERT);
	    }
	}
    }
}

void dscursorblink(void)
{
    if (rp) {
	int wflag = (STYLEFLAG(disp.cury) & DOUBLE_MASK) != 0;

	cursormode = !cursormode;
	if (disp.visual == CUR_BLOCK) {
            BltBitMapRastPort(rp->BitMap, 1, 1, rp, 
			      POSX(disp.curx << wflag),
		              POSY(disp.cury), 
			      wm.font.w << wflag, 
			      wm.font.h, 
			      INVERT);
        }
	else if (disp.visual == CUR_UNDERLINE) {
            BltBitMapRastPort(rp->BitMap, 1, 1, rp,
			      POSX(disp.curx << wflag),
		              POSY(disp.cury) + wm.font.b + 1, 
			      wm.font.w << wflag, 
			      1, 
			      INVERT);
        }
    }
}

long dsflashinit(void)
{
    timereq->tr_time.tv_secs = 1;
    timereq->tr_time.tv_micro = 0;
    timereq->tr_node.io_Command = TR_ADDREQUEST;
    SendIO((struct IORequest *)timereq);

    return 1 << timeport->mp_SigBit;
}

void dscheckflash(void)
{
    register int x, y, xhome;
    int linelen;

    if (CheckIO(timereq)) {
	WaitIO(timereq);
	dsflashinit();
    }

    if (!rp) return;

    flashmode = !flashmode;

    /* flash cursor */
    if (disp.blink) 
	dscursorblink();

    /* flash flashing text  */
    for (y = 0; y < disp.winheight; y++)
	if (STYLEFLAG(y) & FLASH && (linelen = LINELEN(y))) {
	    int wflag = (STYLEFLAG(y) & DOUBLE_MASK) != 0;
	    for (xhome = -1, x = 0; x <= linelen; x++)
		if (x < linelen && (STYLEPOS(x,y) & FLASH)) {
		    if (xhome < 0)
			xhome = x;
		} else if (xhome > -1) {
		    BltBitMapRastPort(rp->BitMap, 0, 0, rp, 
				      POSX(xhome << wflag), POSY(y), 
				      (x - xhome) * wm.font.w << wflag, 
				      wm.font.h, INVERT);
		    xhome = -1;
		} else
		    xhome = -1;
	}
}


/*
 * redraw one line -- used for double width
 */
void redraw_line(int y)
{
    register int    x;
    register char   *temp;
    int		    homex, style, linelen;
    char	    *tempmin, tempc;
    short	    wflag = (STYLEFLAG(y) & DOUBLE_MASK) != 0;

    if (!rp)
	return;

    SETFONT(0, y);
    BltBitMapRastPort(rp->BitMap, 0, 0, rp, POSX(0), POSY(y), 
                      wm.font.w * disp.winwidth, wm.font.h, 
		      disp.invert ? BLACK : WHITE);

    if ((linelen = LINELEN(y)) >= (disp.winwidth >> wflag))
	linelen = (disp.winwidth >> wflag) - 1;

    if (linelen && !STYLEFLAG(y)) {
	temp = (tempmin = TEXTLINE(y)) + linelen;
	tempc = *temp;
	*temp = 0;
	putstring(0, y, tempmin, strlen(tempmin));
	*temp = tempc;
    } else if (linelen && STYLEFLAG(y) > 0) {
	temp = tempmin = TEXTLINE(y);
	style = STYLEPOS(0, y);
	for (homex = x = 0; x <= linelen; x++) {
	    if (x < linelen && STYLEPOS(x, y) == style) {
		temp++;
		continue;
	    }
	    tempc = *temp;
	    *temp = 0;
	    if (style & ATTRIB_MASK)
		SETFONT(style, y);
	    styleput(homex, y, tempmin, x - homex, style);
	    *temp = tempc;
	    tempmin = temp++;
	    if (style & ATTRIB_MASK)
		SETFONT(0, y);
	    if (x < linelen) {
		homex = x;
		style = STYLEPOS(x, y);
	    }
	}
    }
    SETFONT(disp.style, disp.cury);
}

/*
 * redraw the display
 */
void redraw_display(int resize)
{
    register int    x, y;
    register char   *temp;
    int		    homex, style, linelen, wflag;
    char	    *tempmin, tempc;

    if (((resize || !rp) && !resize_display()) || !rp)
	return;

    SETFONT(0, 0);
    if (disp.invert) {
	INVERTALL(BLACK);
    } else
        INVERTALL(WHITE);
    cursormode = 0;
    for (y = 0; y < disp.winheight; y++) {
	wflag = (STYLEFLAG(y) & DOUBLE_MASK) != 0;
	dssetfont(STYLEFLAG(y), y);
	if ((linelen = LINELEN(y)) >= (disp.winwidth >> wflag))
	    linelen = (disp.winwidth >> wflag) - 1;
	if (linelen && !STYLEFLAG(y)) {
	    temp = (tempmin = TEXTLINE(y)) + linelen;
	    tempc = *temp;
	    *temp = 0;
	    putstring(0, y, tempmin, strlen(tempmin));
	    *temp = tempc;
	} else if (linelen != 0 && STYLEFLAG(y) > 0) {
	    temp = tempmin = TEXTLINE(y);
	    style = STYLEPOS(0, y);
	    for (homex = x = 0; x <= linelen + 1; x++) {
		if (x <= linelen && STYLEPOS(x, y) == style) {
		    temp++;
		    continue;
		}
		tempc = *temp;
		*temp = 0;
		if (style & ATTRIB_MASK)
		    SETFONT(style, y);
		styleput(homex, y, tempmin, x - homex, style);
		*temp = tempc;
		tempmin = temp++;
		if (style & ATTRIB_MASK)
		    dssetfont(0, y);
		if (x < linelen) {
		    homex = x;
		    style = STYLEPOS(x, y);
		}
	    }
	}
    }

    if (isSelection()) {
	invertSelection();
    } else {
	dscursoron();
    }
    SETFONT(disp.style, disp.cury);
}

/*
 * Show centered text
 */
void showbanner(struct RastPort *rp, char *text)
{
  size_t l = strlen(text);

  SetWrMsk(rp, 1);

  if (disp.invert) {
    INVERTALL(BLACK);
  } else {
    INVERTALL(WHITE);
  }

  if (wm.x < l * wm.font.w || wm.y < wm.font.h)
    return;

  cursormode = 0;

  Move(rp, (POSX(wm.x) - l * wm.font.w) / 2, (POSY(wm.y) - wm.font.h) / 2);

  if (disp.invert) 
    SetDrMd(rp, DEFDRMD | INVERSVID);

  Text(rp, text, l);

  if (disp.invert) 
    SetDrMd(rp, DEFDRMD);
}


/*
 * scrolling routines
 */
void dsscroll(int y, int numlines, int amount)
{
    if (rp) {
	if (ABS(amount) < numlines) {
	    if(disp.invert) 
		SetBPen(rp, 1);	
	    ScrollRaster(rp, 0, amount*wm.font.h, POSX(0), POSY(y), 
			 POSX(disp.winwidth),
			 POSY(y)+numlines*wm.font.h-1);
	    if(disp.invert) 
		SetBPen(rp, 0);	
	} else if(ABS(amount) >= numlines) 
	    BltBitMapRastPort(rp->BitMap, 0, 0, rp, POSX(0), POSY(y), 
			      wm.font.w*disp.winwidth, numlines*wm.font.h, 
			      disp.invert ? BLACK : WHITE);
    }

    if (ABS(amount) < (numlines)) {
        register char *templ;
        register short *templs;
        register 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 if (amount < 0)
	    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;
	}
    }

    if (amount > 0) {
	MAXBOUNDCK(amount, numlines);
	DSEMPTYLINE(y + numlines - amount, y + numlines);
    } else {
	if ((amount = -amount) > numlines)
	    amount = numlines;
	DSEMPTYLINE(y, y+amount);
    }
}

/*
 * put a string at x, y
 */
static void wmputs(int x, int y, unsigned char *stng, int style)
{
    int len, pos; 
    char temp[MAXWIDTH];
    int wflag = (STYLEFLAG(y) & DOUBLE_MASK) != 0;

    if (disp.insert) {
	register int linelen = LINELEN(y);
	for (pos = 0; pos < MAXWIDTH-1 && (temp[pos] = stng[pos]); pos++);
	for (len = x; pos < MAXWIDTH-1 && len < linelen; len++)
	    temp[pos++] = TEXTPOS(len, y);
	temp[MAXBOUND(pos, (disp.winwidth >> wflag) - 1)] = '\0';
	stng = temp;
    } 
    {
        register int tx = SLIMIT((x),disp.winwidth);
        register int ty = SLIMIT((y),disp.winheight);
        register char *temp = (stng);
        if (temp != NULL && *temp) {
	    for ((len) = LINELEN(ty); (len) < tx; (len)++) {
	        TEXTPOS((len), ty) = ' ';
	        STYLEPOS((len), ty) = 0;
	    }
	    /* stuff the characters into the buffer */
	    for ((len)=0;*temp;) {
	        (len)++;
	        TEXTPOS(tx,ty) = *temp++;
	        STYLEPOS(tx++,ty) = (style);
		if (tx >= disp.winwidth) {
		    LINELENST(ty) = disp.winwidth;
		    tx=disp.winwidth-1;
		    break;
	        }
	    }
	    if (LINELEN(ty) < tx)
	        LINELENST(ty) = tx;
	    STYLEFLAG(y) |= (style);
        }
    }

    if (!rp)
	return;

#if 0    
    BltBitMapRastPort(rp->BitMap, 0, 0, rp, POSX(x << wflag), POSY(y), 
                      wm.font.w * len << wflag, wm.font.h, 
		      disp.invert ? BLACK : WHITE);
#endif

    styleput(x, y, stng, len, style);
}

    
/*
 * quick clear of the entire display
 */
void dsclearscreen(void)
{
    clear_display();
    cursormode = 0;
    if (rp) INVERTALL(disp.invert ? BLACK : WHITE);
    clearSelection();
    dssetfont(disp.style, disp.cury);
}

/*
 * clear region routines
 */
void dsclear(int x, int y, int x1, int y1)
{
    if (x > x1)
	SWAP(x,x1);
    if (y > y1)
	SWAP(y,y1);

    DSCLEAR(x, y, x1, y1);

    if (rp) {
	int wflag = (STYLEFLAG(disp.cury) & DOUBLE_MASK) !=0;
	BltBitMapRastPort(rp->BitMap, 0, 0, rp, 
			  POSX(x << wflag), 
			  POSY(y),
			  (x1 - x + 1) * wm.font.w << wflag, 
			  (y1 - y + 1) * wm.font.h,
			  (disp.invert ? BLACK : WHITE));
    }
}

/*
 * delete n characters on current line into cursor
 */
void dsdelete(int n)
{
    char    deleteme[MAXWIDTH];
    int	    pos, i, linelen = LINELEN(disp.cury);
    int wflag = (STYLEFLAG(disp.cury) & DOUBLE_MASK) != 0;

    if (disp.curx + n >= (disp.winwidth >> wflag))
	n = (disp.winwidth >> wflag) - disp.curx - 1;
    if (!n)
	return;
    if ((pos = disp.curx + n) > linelen) {
	if (linelen > disp.curx)
	    dsclear(disp.curx, disp.cury, linelen, disp.cury);
    } else if (linelen) {
	for (i = 0; pos < linelen; pos++)
	    deleteme[i++] = TEXTPOS(pos, disp.cury);
	deleteme[i] = '\0';
	dsclear(linelen - 1 - n, disp.cury, linelen - 1, disp.cury);
	LINELENST(disp.cury) = linelen-n;
	wmputs(disp.curx, disp.cury, deleteme, disp.style);
    }
}

/*
 * put a string to the display
 */
void dsputs(char *s)
{
    int len = strlen(s), dlen;
    char *temp, tempc;
    int wflag = (STYLEFLAG(disp.cury) & DOUBLE_MASK) != 0;
    
    for (temp = s; len; len -= dlen) {
	if (vt100_yucky_wrap_mode) {
	    disp.curx = 0;
	    NEWLINE();
	    dssetfont(disp.style, disp.cury);
	    vt100_yucky_wrap_mode = 0;
	    wflag = (STYLEFLAG(disp.cury) & DOUBLE_MASK) != 0;
	}
	if (len > (disp.winwidth >> wflag) - disp.curx) {
	    dlen = (disp.winwidth >> wflag) - disp.curx;
	    tempc = temp[dlen];
	    temp[dlen]=0;
	    wmputs(disp.curx, disp.cury, temp, disp.style);
	    temp[dlen] = tempc;
	    if (!disp.wrap)
		dlen = len-1;
	    temp += dlen;
	} else {
	    dlen = len;
	    wmputs(disp.curx, disp.cury, temp, disp.style);
	    if (np.emulation == EMU_VT102 && 
		disp.curx + dlen == (disp.winwidth >> wflag))
		disp.curx--, vt100_yucky_wrap_mode = 1;
	}
	if ((disp.curx += dlen) >= (disp.winwidth >> wflag)) {
	    if (disp.wrap) {
		NEWLINE();
		disp.curx = 0;
	    } else
		disp.curx = (disp.winwidth >> wflag) - 1;
	}

	dssetfont(disp.style, disp.cury);
	if (np.slow) {
	    udelay(100);
	}
    }
}

/*
 * invert screen or visual bell
 */
void dsinvert(int invtype)
{
    if (!rp)
	return;

    switch (invtype) {
	case INVERT_ON:
	    if (!disp.invert) {
		disp.invert = 1;
		INVERTALL(INVERT);
		udelay(8000);
	    }
	    break;

	case INVERT_OFF:
	    if (disp.invert) {
		disp.invert = 0;
		INVERTALL(INVERT);
	    }
	    break;
	    
	case VISUAL_BELL:
            INVERTALL(INVERT);
	    udelay(10000);
            INVERTALL(INVERT);
	    break;
    }
}

/*
 * fill the screen with E's
 */
void dstestscreen(void)
{
    DSTEST('E', disp.style);
    (void) redraw_display(1);
    dscursoroff();
}

/*
 * Routines handling the selection
 */
#define	ISSELECTION \
(selection.sx != selection.ex || selection.sy != selection.ey)
#define	OUTSIDESEL(x,y)	\
    ((y)<selection.sy || ((y)==selection.sy && (x) < selection.sx) ? \
     -1 : \
     ((y)>selection.ey || ((y)==selection.ey && (x) >= selection.ex) ? 1 : 0))
#define	INSEL(x,y)	(!OUTSIDESEL(x,y))
#define	SELTOPY		(selection.sy + (selection.sx ? 1 : 0))
#define	SELBOTY		(selection.ey - 1)
#define	POSITIVE(x)	((x) < 0 ? 0 : (x))
#define	ENDDIST(x,y) \
    (POSITIVE(selection.ey-(y)) * disp.winwidth \
     + disp.winwidth - 1 - (x) + selection.ex)
#define	STDIST(x,y) \
    (POSITIVE((y)-SELTOPY-1) * disp.winwidth  \
     + disp.winwidth - 1 - selection.sx + (x))
#define	NEAREND(x,y)	(ENDDIST(x,y) > STDIST(x,y))
#define	REVSEL \
(selection.sy > selection.ey || \
 (selection.sy == selection.ey && selection.sx > selection.ex))

struct {
    int	sx, sy,	ex, ey;		/* selection range */
} selection;

/* Returns true if selected
 */
int isSelection(void) {
    return ISSELECTION;
}

/* Mouse selection handler
 */
void doselection(int action, int x, int y)
{
    int selection_on = ISSELECTION;

    if (!rp)
      return;

    if (action == LBDOWN) {
	if (ISSELECTION)
	    killSelection();
	selection.sx = selection.ex = x;
	selection.sy = selection.ey = y;

    } 
    else if((action == LBUP) || (action == LMOVE)) {
	if (selection.ex != x || selection.ey != y)
	    extendSelection(selection.ex,selection.ey,x,y);
	selection.ex=x;
	selection.ey=y;
	if(action == LBUP) {
		register int tmp;
		tmp=selection.sy, selection.sy=selection.ey, selection.ey=tmp;
		tmp=selection.sx, selection.sx=selection.ex, selection.ex=tmp;
	}
    }
    if (ISSELECTION ^ selection_on)
	dscursorblink();	
}

/*
 * grab a selection -- caller must free the buffer when finished.
 */
char *grabSelection(void)
{
    char *buffer, *temp;
    int sx = selection.sx, ex = selection.ex, endx, endl;
    int sy = selection.sy, ey = selection.ey;
    int buflen;

    if (!ISSELECTION)
	return (NULL);

    if (sy > ey || (sy == ey && sx > ex)) {
	register int tmp;

	tmp = sy, sy=ey, ey = tmp;
	tmp = sx, sx=ex, ex = tmp;
    }

    buflen = (ey - sy + 2) * (disp.winwidth + 1); 
    temp = buffer = AllocVec(buflen, MEMF_CLEAR);

    for (;sy <= ey; sy++) {
	endx = LINELEN(sy);
	if (sy == ey) {
	    MAXBOUNDCK(endx, ex);
	    endl = ex;
	} else
	    endl = disp.winwidth;
	for (;sx < endx; sx++)
	    *temp++ = TEXTPOS(sx, sy);
	sx = 0;
	if (endl > LINELEN(sy))
	    *temp++ = '\n';
    }
    *temp = 0;

    assert(temp < buffer + buflen);

    return (buffer);
}

/* invert/extend the selection range
 */
void extendSelection(int sx, int sy, int ex, int ey)
{
  int topy, boty;

  if (sy > ey || (sy == ey && sx > ex)) {
    register int tmp;

    tmp = sy, sy=ey, ey = tmp;
    tmp = sx, sx=ex, ex = tmp;
  }
  topy = sy + (sx ? 1 : 0);
  boty = ey - 1;
  if (sx == ex && sy == ey)
    return;
  if (sy == ey) 
    BltBitMapRastPort(rp->BitMap, 0, 0, rp, POSX(sx), POSY(sy), 
		      wm.font.w*(ex-sx), wm.font.h, INVERT);
  else {
    if (sx && sx < disp.winwidth)
      BltBitMapRastPort(rp->BitMap, 0, 0, rp, POSX(sx), POSY(sy),
			wm.font.w*(disp.winwidth-sx), wm.font.h, INVERT);
    if (boty-topy+1 > 0)
      BltBitMapRastPort(rp->BitMap, 0, 0, rp, POSX(0), POSY(topy),
			wm.font.w * disp.winwidth, 
			wm.font.h * (boty - topy + 1), INVERT);
    if (ex)
      BltBitMapRastPort(rp->BitMap, 0, 0, rp, POSX(0), POSY(ey), 
			wm.font.w*ex, wm.font.h, INVERT);
  }
}

void invertSelection(void)
{
    extendSelection(selection.sx, selection.sy, selection.ex, selection.ey);
}

void killSelection(void)
{
    invertSelection();
    selection.ey=selection.sy;
    selection.ex=selection.sx;
}

void clearSelection(void)
{
    selection.ey = selection.sy = selection.ex = selection.sx = 0;
}

/*
 * Initialization and cleanup
 */
int initdrawing(struct RastPort *rastport)
{
  if (!rp) {
    myrp = *(rastport);
    rp = &myrp;

    SetAPen(rp, 1);
    SetBPen(rp, 0);
    SetWrMsk(rp, 1);
    SetDrMd(rp, DEFDRMD);
    return 1;
  } else {
    return 0;
  }
}

void deinitdrawing(void)
{
    rp = NULL;
}

#ifdef OWNICONIFY
/* Do Not do ANYTHING after calling unmapwindow!! This is only used for 
 * iconification.  Saves the state information, then closes the window.
 */
void
unmapwindow(void)
{
    struct IntuiMessage *msg;
    
    while (msg = (struct IntuiMessage *)
	   GetMsg(w->UserPort)) ReplyMsg((struct Message *)msg);
    DisplayOff = 1;
    ClearMenuStrip(w);
    nw.TopEdge = w->TopEdge;
    nw.LeftEdge = w->LeftEdge;
    nw.Width = w->Width;
    nw.Height = w->Height;
    nw.MaxWidth = w->MaxWidth;
    nw.MaxHeight = w->MaxHeight;
    nw.MinWidth = w->MinWidth;
    nw.MinHeight = w->MinHeight;
    nw.Flags = w->Flags;
    nw.Title = w->Title;
    CloseWindow(w);
    rp = w = NULL;			/* no dangling references */
}

/* Undoes a call to unmapwindow() everything should return to the way it was
 * before the call 
 */
void
mapwindow(void) 
{
    if(!(w = OpenWindow(&nw))) 
        fatalError("Can't reopen window!!!!!");
    /* We have a new RastPort!! */
    myrp = *(w->RPort);
    rp = &myrp;
    SetAPen(rp, 1);
    SetBPen(rp, 0);
    SetWrMsk(rp, 1);
    SetDrMd(rp, DEFDRMD);

    /* => setmenus() */
    SetMenuStrip(w, &editmenu);
    /* Now, everything should be back the way it was before */
    DisplayOff = 0;
    redraw_display(1);
}
#endif

/* Local Variables: */
/* c-style:C++ */
/* End: */
