/*
 * 5799-WZQ (C) COPYRIGHT IBM CORPORATION 1986,1987
 * LICENSED MATERIALS - PROPERTY OF IBM
 * REFER TO COPYRIGHT INSTRUCTIONS FORM NUMBER G120-2083
 */
/* $Header:monotty.c 12.0$ */
/* $ACIS:monotty.c 12.0$ */
/* $Source: /ibm/acis/usr/sys/standca/RCS/monotty.c,v $ */

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

/* $Header:monotty.c 12.0$ */
/* $ACIS:monotty.c 12.0$ */
/* $Source: /ibm/acis/usr/sys/standca/RCS/monotty.c,v $ */
#include "mono.h"

#if NMONO > 0

/************************************************************************/
/*									*/
/*	Routines to Handle the MONOcrome Screen (memory mapped).	*/
/* We implement a simple termcap for now in software.			*/
/*									*/
/************************************************************************/

#include "param.h"
#include "screen_conf.h"
#include "consdefs.h"
#include "monotty.h"
#include "mono_tcap.h"

#include "../standca/sa.h"

/*
 * Output Driver for a PC MONOCROME screen adapter on a RT PC.
 */

#ifdef ATR
char *screen_buffer;
#else
#ifdef IBMRTPC
char *screen_buffer = SCREEN_BUFFER;
#endif IBMRTPC
#endif ATR
extern int lpstatus;

LOCAL char *lines[MONO_SCREEN_LENGTH + 1] = {
	0
};				       /* pointer to start of lines */
LOCAL char *screen_ptr = 0;
int screen_size;			/* mono screen size */

#ifndef ATR
#define move_block bcopy
#endif  ATR

mono_screen_init()
{
	register char *p = SCREEN_BUFFER;
	register int i;

	screen_size = MONO_SCREEN_WIDTH * MONO_SCREEN_LENGTH * 2;
	screen_ptr = p;
/* note the <=. This so that lines[screen_length] is the end of the buffer */
	for (i = 0; i <= MONO_SCREEN_LENGTH; ++i) {
		lines[i] = p;
		p += (MONO_SCREEN_WIDTH << 1);
	
	}
	mono_screen_clear();
}

LOCAL
mono_screen_clear (si)
register SCREEN_INFO *si;
{
	mono_screen_blank (NORMAL_VIDEO, 0, 0, MONO_SCREEN_LENGTH-1, MONO_SCREEN_WIDTH-1);
	mono_pos_cursor (0, 0);
}

LOCAL
mono_screen_attr(sa)
register int sa;
{
	register int ma;	/* Mono attribute */

	if (sa & NORMAL_VIDEO)
		ma = MONO_NORMAL_VIDEO;
	else if (sa & REVERSE_VIDEO)
		ma = MONO_REVERSE_VIDEO;
	else if (sa & UNDERLINE_VIDEO)
		ma = MONO_UNDERLINE_VIDEO;

	if (sa & HI_INTENSITY)
		ma |= MONO_HI_INTENSITY;
	if (sa & BLINK)
		ma |= MONO_BLINK;

	return (ma);
		
}

mono_screen_putc(c, sa)
register int c;		/* Character to put on screen
register int sa;	/* Screen Attribute */
{
	/* Monochrome attribute field */
	static int mono_attr = MONO_NORMAL_VIDEO;
	/* Last Screen Attribute */
	static int la = NORMAL_VIDEO;

	/*
	 * output the given character with the screen attribute
	 */
	PUT_PC1B(*screen_ptr,(char) c);
	if (sa != la)
		mono_attr = mono_screen_attr (sa);
	PUT_PC1B(*(screen_ptr + 1), mono_attr);
	la = sa;
}


/*
 * blank the given line (line), starting at the given position (position)
 * giving proper number of blanks (width)
 */
mono_screen_blank(screen_attr, sy, sx, ey, ex)
	register int screen_attr, sy, sx, ey, ex;
{
	register short *ptr = (short *)(lines[sy] + (sx << 1)),
	*end = (short *)(lines[ey] + (ex << 1));
	register int width = end - ptr;

EDEBUG (0x02, aed_pr("MONO_SCREEN_BLANK\n\r"));
#define fill sy

#ifdef ATR
	set_128_window(screen_addr(CONS_MONO));
#endif ATR
	fill = (' ' << 8) + mono_screen_attr (screen_attr);
	fill = (fill << 16) + fill;
	if ((int)ptr & 02) {
		PUT_PC2B(*ptr++,fill);        /* align to word bdy */
		--width;
	}
	while ((width -= 8) >= 0) {
		register int *wptr = (int *)ptr;

		PUT_PC4B(wptr[0], fill);
		PUT_PC4B(wptr[1], fill);
		PUT_PC4B(wptr[2], fill);
		PUT_PC4B(wptr[3], fill);
		ptr = (short *)(wptr + 4);
	}
	while (ptr <= end)
		PUT_PC2B(*ptr++, fill);
EDEBUG (0x02, aed_pr("leave mono_screen_blank\n\r"));
}


#undef fill


/*
 * move line1 ... line2 to dest
 */
mono_screen_move(line1, line2, dest)
	register int line1, line2, dest;
{
	register char *start = lines[line1], *end = lines[line2 + 1];
EDEBUG (0x02, aed_pr("MONO_SCREEN_MOVE\n\r"));
	if (line1 > dest)
		move_block(start, lines[dest], end - start);
	else if (line1 != dest)
		rmove_block(start, lines[dest], end - start);
EDEBUG (0x02, aed_pr("leave mono_screen_move\n\r"));
}


#ifndef move_block
LOCAL
move_block(from, to, length)
	register int *from, *to, length;
{

#ifdef ATR
	set_128_window(screen_addr(CONS_MONO));
#endif
	length >>= 2;		       /* get as int's */
	while (--length >= 0) {
		PUT_PC4B(*to++,GET_PC4B(*from++));
	}
}


#endif

#ifndef rmove_block
LOCAL
rmove_block(from, to, length)
	register int *from, *to, length;
{
#ifdef ATR
	set_128_window(screen_addr(CONS_MONO));
#endif ATR
	from = (int *)(((int)from) + length);
	to = (int *)(((int)to) + length);
	length >>= 2;		       /* get as int's */
	while (--length >= 0)
		PUT_PC4B(*--to,GET_PC4B(*--from));
}


#endif

mono_pos_cursor(x, y)
register int x, y;
{
	register int pos;

	set_ptr (x, y);
	pos = (screen_ptr - SCREEN_BUFFER) >> 1;
EDEBUG (0x01, aed_pr("mono_pos_cursor (%d, %d) (%d):(%x)x\n", x, y, pos, screen_ptr));

	PUT_SCR_REG(14, pos >> 8);
	PUT_SCR_REG(15, pos);
}



/*  Set up the 128K byte window for screen access.  */

mono_probe(rwaddr)
char *rwaddr;
{
#ifdef ATR
	/* Get the screen buffer offset into the 128K window */
	mono_screen_buffer = (char *)set_128_window(screen_addr(CONS_MONO));
				/* Place it into the screen switch table */
	screen_sw[CONS_MONO].rwaddr = mono_screen_buffer; 
	screen_buffer = mono_screen_buffer;
#endif ATR

	return(screen_probe(screen_buffer));
}

/*
 * screen printing functions:
 * flag == 0	print the current screen contents
 * flag != 0	invert the log output flag
 */
mono_screen_print(si, flag)
register SCREEN_INFO *si;
register int flag;
{
	register int l, i;
	register char *p = SCREEN_BUFFER;

	/* print out the monochrome screen buffer on the printer */

	for (l = 0; l < SCREEN_LENGTH; ++l) {
		p = lines[l];
		for (i = 0; i < SCREEN_WIDTH; ++i, p += 2) {
			mono_pos_cursor (i, l);
			if (lp_put(GET_PC1B(*p))) {
				hard_delay(250);
				goto done; /* quit if error */
			}
		}
		lp_put('\r');
		lp_put('\n');
	}
	lp_put('\f');		       /* skip to top of form */
done:
	put_status(33, "        ");
	lpstatus = -1;
}

/*
 * these are called from screendev via screen_sw table
 */
monoopen()
{
	return(0);
}

monoclose()
{
	return(0);
}
#endif NMONO
