/*
 * Amiga system-dependent routines. 
 */

#include <proto/dos.h>
#include "stevie.h"

long            raw_in = 0;
long            raw_out = 0;

#define	BSIZE	2048
static char     outbuf[BSIZE];
static int      bpos = 0;

void
flushbuf()
{
    if (bpos != 0)
	Write(raw_out, outbuf, bpos);
    bpos = 0;
}

/*
 * Macro to output a character. Used within this file for speed. 
 */
#define	outone(c)	outbuf[bpos++] = c; if (bpos >= BSIZE) flushbuf()

int
GetCharacter()
{
    char            c;

    Read(raw_in, &c, sizeof(c));
    return ((int) c);
}

/*
 * getCSIsequence - get a CSI sequence
 *                - either cursor keys, help, functionkeys, or some
 *                  other sequence (if other, check window size)
 */
int
getCSIsequence()
{
    int             c;
    int             param1;
    int             param2;

    c = GetCharacter();
    if (isdigit(c)) {
	param1 = 0;
	while (isdigit(c)) {
	    param1 = param1 * 10 + c - '0';
	    c = GetCharacter();
	}
	if (c == '~')		/* function key */
	    return ((char) (K_F1 + param1));

	/* must be an event of some sort or a window bound report */
	if (c == ';') {
	    param2 = 0;
	    c = GetCharacter();
	    while (isdigit(c)) {
		param2 = param2 * 10 + c - '0';
		c = GetCharacter();
	    }
	    if (c == ';') {
		param1 = 0;
		c = GetCharacter();
		while (isdigit(c)) {
		    param1 = param1 * 10 + c - '0';
		    c = GetCharacter();
		}
		if (c == ';') {
		    param2 = 0;
		    c = GetCharacter();
		    while (isdigit(c)) {
			param2 = param2 * 10 + c - '0';
			c = GetCharacter();
		    }
		    if (c == ' ') {
			c = GetCharacter();
			if (c == 'r') {
			    if (param1 < 2)
				param1 = 2;
			    if (param2 < 5)
				param2 = 5;
			    if (Columns != param2 || Rows != param1) {
				Columns = param2;
				Rows = param1;
				P(P_LI) = Rows;
				return (-1);
			    } else
				return 0;
			}
		    }
		}
	    }
	}
	while ((c != '|') && (c != '~'))
	    c = GetCharacter();

	outstr("\033[0 q");
	flushbuf();
    }
    switch (c) {
      case 'A':		/* cursor up */
	return K_UARROW;
      case 'B':		/* cursor down */
	return K_DARROW;
      case 'C':		/* cursor right */
	return K_RARROW;
      case 'D':		/* cursor left */
	return K_LARROW;
      case 'T':		/* shift cursor up */
	return K_SUARROW;
      case 'S':		/* shift cursor down */
	return K_SDARROW;
      case ' ':		/* shift cursor left or right */
	c = GetCharacter();
	if (c == 'A')		/* shift cursor left */
	    return K_SLARROW;
	if (c == '@')		/* shift cursor right */
	    return K_SRARROW;
	break;
      case '?':		/* help */
	c = GetCharacter();
	if (c == '~')
	    return K_HELP;
	break;
    }
    return 0;			/* some other control code */
}

/*
 * inchar() - get a character from the keyboard 
 */
int
inchar()
{
    int             c;

    flushbuf();

    for (;;) {
	c = GetCharacter();
	if (c != 0x9b)
	    break;
	c = getCSIsequence();
	if (c > 0)
	    break;
	if (c == -1) {
	    screenalloc();
	    screenclear();
	    msg("");
	    updateNextscreen(NOT_VALID);
	    cursupdate();
	    updateNextscreen(NOT_VALID);
	    cursupdate();
	    updateRealscreen();
	    windgoto(Cursrow, Curscol);
	    flushbuf();
	}
    }
    return c;
}

void
outchar(c)
    char            c;
{
    outbuf[bpos++] = c;
    if (bpos >= BSIZE)
	flushbuf();
}

void
outstr(s)
    char           *s;
{
    while (*s)
	outone(*s++);
}

void
beep()
{
    if (RedrawingDisabled)
	return;

    outone('\007');
}

void
sleep(n)
    int             n;
{
    void            Delay();

    if (n > 0)
	Delay(50L * n);
}

void
delay()
{
    void            Delay();

    Delay(25L);
}

void
windinit()
{
    Columns = 80;
    P(P_LI) = Rows = 24;

    raw_in = Input();
    if (!IsInteractive(raw_in)) {
	raw_in = Open("RAW:0/0/480/200/STEVIE", MODE_NEWFILE);
	if (raw_in == NULL) {
	    fprintf(stderr, "Can't open window ?!?!?!?\n");
	    exit(2);
	}
	raw_out = raw_in;
    } else {
	raw_out = Output();
	if (raw(stdin) != 0)
	    perror("Can't change to raw mode ?!?!?!?");
    }

    outstr("\033[12{");		/* window resize events activated */
    flushbuf();

    for (;;) {
	outstr("\033[0 q");	/* get window size */
	flushbuf();
	if (GetCharacter() == 0x9b)
	    if (getCSIsequence() == -1)
		break;
    }
}

void
windexit(r)
    int             r;
{
    outstr("\033[12}");		/* window resize events de-activated */
    flushbuf();

    if (raw_in != raw_out) {
	if (cooked(stdin) != 0)
	    perror("Can't change to cooked mode ?!?!?!?");
    } else {
	Close(raw_in);
    }
    exit(r);
}

void
windgoto(r, c)
    int             c;
    int             r;
{
    r++;
    c++;

    outstr("\033[");
    if (r >= 10)
	outchar((char) (r / 10 + '0'));
    outchar((char) (r % 10 + '0'));
    outchar(';');
    if (c >= 10)
	outchar((char) (c / 10 + '0'));
    outchar((char) (c % 10 + '0'));
    outchar('H');
}

FILE           *
fopenb(fname, mode)
    char           *fname;
    char           *mode;
{
    FILE           *fopen();
    char            modestr[16];

    sprintf(modestr, "%sb", mode);
    return fopen(fname, modestr);
}
