/****************************************************
* vt100 emulator - remote character interpretation
*    v1.0  DBW   860621   Dave Wecker
****************************************************/

#define MODULE_REMOTE 1
#include "vt100.h"

static USHORT top       = MINY;
static USHORT bot       = MAXY;
static USHORT savx      = MINX;
static USHORT savy      = MINY;
static USHORT savmode   = 0;
static USHORT nlmode    = 0;
static USHORT alt       = 0;
static USHORT savalt    = 0;
static USHORT a[2]      = { 0, 0 };
static USHORT sa[2]     = { 0, 0 };
static short  inesc     = -1;

static short  p1,p2,numpar;
static char   escseq[40];

/************************************************
*  function to handle remote characters
*************************************************/
doremote(c)
char c;
    {
    if (c == 27 || inesc >= 0) { doesc(c); return; }
    if (c == 10 || c == 11 || c == 12) {
	if (nlmode) doindex('E'); else doindex('D');
	return;
	}
    if (c == 13) {
	if (!nlmode) emit(c);
	return;
	}
    if (c == 15) { alt = 0; return; }
    if (c == 14) { alt = 1; return; }
    if (a[alt] && c > 94 && c < 127) { doalt(c); return; }
    emit(c);
    }

doesc(c)
char c;
    {
    if (inesc < 0) { inesc = 0; return; }
    if (c == 27 || c == 24) { inesc = -1; return; }
    if (inesc == 0) {
	if (c == '[' || c == '#' || c == '(' || c == ')') {
	    numpar = 0;
	    escseq[inesc++] = c;
	    return;
	    }
	if (c == 'D' || c == 'E' || c == 'M') {
	    inesc = -1;
	    doindex(c);
	    return;
	    }
	if (c == '7') {
	    inesc = -1;
	    savx = x; savy = y; savmode = curmode; savalt = alt;
	    sa[0] = a[0]; sa[1] = a[1];
	    return;
	    }
	if (c == '8') {
	    inesc = -1;
	    x = savx; y = savy; alt = savalt; curmode = savmode;
	    a[0] = sa[0]; a[1] = sa[1];
	    return;
	    }
	if (c == 'c') {
	    inesc = -1;
	    top = MINY; bot = MAXY; savx = MINX; savy = MINY;
	    a[0] = 0; a[1] = 0; sa[0] = 0; sa[1] = 0;
	    emit(12); return;
	    }
	inesc = -1;
	return;
	}
    if (inesc == 1 && escseq[0] == '#') { inesc = -1; return; }
    if (inesc == 1 && escseq[0] == '(') {
	inesc = -1;
	if (c == '0' || c == '2') a[0] = 1; else a[0] = 0;
	return;
	}
    if (inesc == 1 && escseq[0] == ')') {
	inesc = -1;
	if (c == '0' || c == '2') a[1] = 1; else a[1] = 0;
	return;
	}
    if ((c >= '0' && c <= '9') || c == ';' || c == '?') {
	if (inesc == 1) numpar = 1;
	if (c == ';') numpar++;
	escseq[inesc++] = c;
	return;
	}
    escseq[inesc] = '\000';
    inesc = -1; p1 = -1; p2 = -1;
    if (escseq[1] == '?') return;
    switch (numpar) {
	case 1: sscanf(escseq,"[%d",         &p1);             break;
	case 2: sscanf(escseq,"[%d;%d",      &p1,&p2);         break;
	case 3: sscanf(escseq,"[%d;%d;%d",   &p1,&p2,&p2);     break;
	case 4: sscanf(escseq,"[%d;%d;%d;%d",&p1,&p2,&p2,&p2); break;
	}
    if (c >= 'A' && c <= 'D') {
	if (p1 <= 0) p1 = 1;
	switch (c) {
	    case 'A':   y -= 8*p1; if (y<top)  y = top;  break;
	    case 'B':   y += 8*p1; if (y>bot)  y = bot;  break;
	    case 'C':   x += 8*p1; if (x>MAXX) x = MAXX; break;
	    case 'D':   x -= 8*p1; if (x<MINX) x = MINX; break;
	    }
	return;
	}
    if (c == 'H' || c == 'f') {
	if (p1 <= 0) p1 = 1;
	if (p2 <= 0) p2 = 1;
	y = (--p1*8)+MINY; x = (--p2*8)+MINX;
	if (y > MAXY) y = MAXY;
	if (x > MAXX) x = MAXX;
	if (y < MINY) y = MINY;
	if (x < MINX) x = MINX;
	return;
	}
    if (c == 'r') {
	if (p1 <= 0) p1 = 1;
	if (p2 <= 0) p2 = 24;
	top = (--p1*8)+MINY; bot = (--p2*8)+MINY;
	if (top < MINY) top = MINY;
	if (bot > MAXY) bot = MAXY;
	if (top > bot) { top = MINY; bot = MAXY; }
	return;
	}
    if (c == 'm') {
	if (p2 >= 0) p1 = p2;
	if (p1 <= 0) curmode = 0; else curmode = 1;
	return;
	}
    if (c == 'K') {
	doerase();
	return;
	}
    if (c == 'J') {
	if (p1 < 0) p1 = 0;
	SetAPen(mywindow->RPort,0L);
	if (p1 == 0) RectFill(mywindow->RPort,
	    (long)MINX,(long)(y+2),(long)(MAXX+7),(long)(bot+2));
	else if (p1 == 1) RectFill(mywindow->RPort,
	    (long)MINX,(long)(top-7),(long)(MAXX+7),(long)(y-7));
	else RectFill(mywindow->RPort,
	    (long)MINX,(long)(top-7),(long)(MAXX+7),(long)(bot+2));
	SetAPen(mywindow->RPort,1L);
	doerase(); return;
	}
    if (c == 'h') {
	if (p1 == 20) nlmode = 1;
	return;
	}
    if (c == 'l') {
	if (p1 == 20) nlmode = 0;
	return;
	}
    if (c == 'x') {
	sendchar(27); sendstring("[3;1;8;64;64;1;0x"); return;
	}
    if (c == 'n') {
	if (p1 == 6) {
	    sendchar(27);
	    sprintf(escseq,"[%d;%dR",((y-MINY)/8)+1,((x-MINX)/8)+1);
	    sendstring(escseq); return;
	    }
	sendchar(27); sendstring("[0n"); return;
	}
    if (c == 'c') {
	sendchar(27); sendstring("[?1;0c"); return;
	}
    }

doindex(c)
char c;
    {
    inesc = -1;
    if (c != 'M') {
	if (y > bot) { top = MINY; bot = MAXY; y = bot; }
	if (y == bot) {
	    ScrollRaster(mywindow->RPort,0L,8L,MINX,(long)(top-6),
		(long)(MAXX+7),(long)(bot+1));
	    y -= 8;
	    }
	if (c == 'E') x = MINX;
	y += 8;
	}
    else {
	if (y < top) { top = MINY; bot = MAXY; y = top; }
	if (y == top) {
	    ScrollRaster(mywindow->RPort,0L,-8L,(long)MINX,(long)(top-7),
		(long)(MAXX+7),(long)(bot+1));
	    y += 8;
	    }
	y -= 8;
	}
    return;
    }

doalt(c)
char c;
    {
    short oldx,newx;
    inesc = -1;
    oldx = x; emit(' '); newx = x;
    x = oldx;
    SetAPen(mywindow->RPort,1L);
    switch (c) {
	case 'j':
	case 'm':
	case 'v':   doline(4,-8,4,-4);
	if      (c=='j')  doline(0,-4,4,-4);
	else if (c=='m')  doline(4,-4,8,-4);
	else              doline(0,-4,8,-4);
	break;

	case 'k':
	case 'l':
	case 'w': doline(4,-4,4,0);
	if      (c=='k')  doline(0,-4,4,-4);
	else if (c=='l')  doline(4,-4,8,-4);
	else              doline(0,-4,8,-4);
	break;

	case 'n':
	case 'q': doline(0,-4,8,-4);
	if      (c=='n')  doline(4,-8,4,0);
	break;

	case 't':
	case 'u':
	case 'x':   doline(4,-8,4,0);
	if      (c=='t')  doline(4,-4,8,-4);
	else if (c=='u')  doline(0,-4,4,-4);
	break;
	}
    x = newx;
    }

doline(x1,y1,x2,y2) {
    RectFill(mywindow->RPort,(long)(x+x1),(long)(y+y1),
	(long)(x+x2),(long)(y+y2));
    }

doerase()
    {
    inesc = -1;
    if (p1 < 0) p1 = 0;
    SetAPen(mywindow->RPort,0L);
    if (p1 == 0) RectFill(mywindow->RPort,(long)x,(long)(y-6),
	(long)(MAXX+7),(long)(y+1));
    else if (p1 == 1) RectFill(mywindow->RPort,
	(long)MINX,(long)(y-6),(long)(x+7),(long)(y+1));
    else RectFill(mywindow->RPort,
	(long)MINX,(long)(y-6),(long)(MAXX+7),(long)(y+1));
    SetAPen(mywindow->RPort,1L);
    return;
    }
