/*
 * ansicon.c, part of libvt for c68 v4.x        20.12.93 jh
 * 
 */
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <fcntl.h>
#include <qdos.h>

#define YINC 10
#define XINC 6

#include "ansicon.h"

ANSICONDEF __ANSICONF__ = {VT100, 0};

extern char _ANSIChr_[], _ANSICtl_[], _DECGraf_[];

static unsigned char bCR = FALSE;

static int pChId;
static char nTab;
static unsigned char SYtop, SYbot, SYEnd;
static char TabBuf[80];
static unsigned char RelOrg;
static char sfCol, sbCol, sXpos, sYpos;
static char bScroll, jScroll ;
static char RCFlag;
static char sWrap;
static char sOrigin;
static char sSet[2];
static char svtMode;
static char abold, sbold;
static short ReDef[4];
static char lastemu = -1;

static char NrmFCol[] = {GREEN_M4, BLACK_M4};
static char BoldCol[] = {WHITE_M4, BLACK_M4};
static char FlashC[] = {RED_M4, BLACK_M4};
static char ColorTab[] = {GREEN_M4, GREEN_M4, RED_M4, RED_M4, BLACK_M4, BLACK_M4, WHITE_M4, WHITE_M4};
static unsigned char ANSITab[2][8] =
{
    {0, 2, 4, 242, 246, 226, 20, 7},
    {63, 80, 44, 50, 126, 26, 60, 22}};
static unsigned char ANSIBold[8] = {WHITE_M4, RED_M4, GREEN_M4, WHITE_M4, WHITE_M4, RED_M4, GREEN_M4, WHITE_M4};

static short ConDef[4];

static int ini = 0;

ANSI_conwrite(struct UFB *, char *, int);

static ReadCsr (int pChId, short *pXpos, short *pYpos);
static VTInit (int flg);
static VT100Esc (char ch);
static SaveCursor (void);
static LoadCursor (void);
static EscVT100 (void);
static VTSquare (char ch1);
static ClearToCursor (void);
static VTHash (char ch1);
static NewLine (void);
static WriteChar (unsigned char ch);
static NextTabStop (void);
static AddTabList (void);
static RemTabList (void);
static ScrollTop (void);
static ScrollScreen (int dirn);
static NewPos (int apos);
static Colour (int chan, int bcol, int fcol);
static VT52Esc (char ch);
static AddEscBuffer (char ch);
static DoEscSeq (void);
static ProcessNorm (unsigned char ch);
static CanSub (char ch);
static ReadCsr (int pChId, short *pXpos, short *pYpos);
extern int win_enq (int pChId, short *ConDef);

static VTInit (int flg)
{
    int i;

    if(ini == 0)
    {
        Xpos = Ypos = 0;
        sCount = 1;
        sState = SNORM;
        pEscBuf = EscBuf;
        bRXEOL = EOLLF;

        win_enq (pChId, ConDef);
        SYEnd = ConDef[1] / YINC - 1;
        ReDef[0] = ConDef[0];
        ReDef[2] = ConDef[2];
        jScroll = 0;
        ini = 1;
    }

    if (__ANSICONF__.emulation != lastemu)
    {
        if (__ANSICONF__.emulation & ANSI_M)
	{
            sd_fount(pChId, -1, NULL, _ANSIChr_);
	}
	else
	{
	    sd_fount (pChId, -1, NULL, NULL);
	}
        lastemu = __ANSICONF__.emulation;
    }

    abold = sbold = 0;
    nTab = 9;
    SYtop = 0;
    SYbot = SYEnd;

    for (i = 0; i < nTab; i++)
    {
	TabBuf[i] = 8 * (i + 1);
    }
    RelOrg = sOrigin = FALSE;
    vtMode = svtMode = 0;
    cSet[0] = sSet[0] = C_TEXT;
    cSet[1] = sSet[1] = C_GRAF;
    sXpos = 0;
    sYpos = 0;
    bScroll = 0;
    RCFlag = 0;
    bInsert = 0;
    bWrap = sWrap = 1;
    if (__ANSICONF__.emulation & ANSI_M)
    {
	Colour (pChId, (int) (sbCol = bCol = BLACK_M4), (int) (sfCol = fCol = WHITE_M4));
	NrmFCol[0] = WHITE_M4;
	BoldCol[0] = GREEN_M4;
    }
    else
    {
	Colour (pChId, (int) (sbCol = bCol = BLACK_M4), (int) (sfCol = fCol = GREEN_M4));
	NrmFCol[0] = GREEN_M4;
	BoldCol[0] = WHITE_M4;
    }
    sd_setpa (pChId, -1, (int) bCol);

    if (flg)
    {
        sd_pos (pChId, -1, 0, 0);
	sd_clear (pChId, -1);
    }
}
int ANSI_conwrite(struct UFB *uptr, char *bptr, int blen)
{
    unsigned char ch;
    int ix;

    unsigned char *cbptr = (unsigned char *)bptr;
    
    pChId = uptr->ufbfh;

    if(ini == 0)
    {
        VTInit(0);
    }

    if (__ANSICONF__.emulation != lastemu)
    {
        VTInit(0);
    }    

    for(ix = 0; ix < blen; ix++)
    {
        ch = *cbptr++;

    	switch (sState)
	{
	    case SNORM:
		ProcessNorm (ch);
		break;
	    case SESC:
		switch (__ANSICONF__.emulation)
		{
		    case VT52:
			VT52Esc (ch);
			break;
		    case VT100:
		    case ANSI1:
		    case ANSI2:
		    case ANSI3:
		    case ANSI4:
			VT100Esc (ch);
			break;
		}
		break;
	    default:
		if (sState != SESCEX)
		{
		    AddEscBuffer (ch);
		}
		break;
	}
	if (sState == SESCEX)
	{
	    ReadCsr (pChId, &Xpos, &Ypos);
	    DoEscSeq ();
	}
    }
    return -blen;
}

VT100Esc (char ch)
{
    *pEscBuf++ = ch;

    switch (ch)
    {
	case SS:
	case CAN:
	    CanSub (ch);
	    break;
	case '[':
	    sState = SESCPM;
	    break;

	case '#':
	    sState = SESCNO;
	    break;

	case '(':
	case ')':
	case '*':
	case '+':
	    sState = SESCGx;
	    break;

	default:
	    sState = SESCEX;
	    break;
    }
}
static SaveCursor (void)
{
    sbCol = bCol;
    sfCol = fCol;
    sXpos = Xpos;
    sYpos = Ypos;
    sSet[0] = cSet[0];
    sSet[1] = cSet[1];
    sWrap = bWrap;
    svtMode = vtMode;
    sOrigin = RelOrg;
    sbold = abold;
}
static LoadCursor (void)
{
    Colour (pChId, (int) (bCol = sbCol), (int) (fCol = sfCol));
    sd_pos (pChId, -1, (int) sXpos, (int) sYpos);
    cSet[0] = sSet[0];
    cSet[1] = sSet[1];
    bWrap = sWrap;
    vtMode = svtMode;
    RelOrg = sOrigin;
    abold = sbold;
}

static EscVT100 ()
{
    char ch0;
    char ch1;
    int s;

    ch0 = EscBuf[0];
    ch1 = *(--pEscBuf);

    switch (ch0)
    {
	case '[':
	    VTSquare (ch1);
	    break;
	case '#':
	    VTHash (ch1);
	    break;
	case '(':
	case ')':
	case '*':
	case '+':
	    if (ch0 == '(')
	    {
		s = 0;
	    }
	    else
	    {
		s = 1;
	    }
	    if (ch1 == '0')
	    {
		cSet[s] = C_GRAF;
	    }
	    else
	    {
		cSet[s] = C_TEXT;
	    }
	    break;
	default:
	    switch (ch0)
	    {
		case '7':
		    SaveCursor ();
		    break;
		case '8':
		    LoadCursor ();
		    break;
		case 'H':
		    AddTabList ();
		    break;

		    /* Ignore = > to set keypad modes */

		case 'c':
		    VTInit (1);
		    break;
		case 'M':
		    ScrollTop ();
		    break;
		case 'D':
		    NewLine ();
		    sd_tab (pChId, -1, Xpos);
		    break;
		case 'E':
		    NewLine ();
		    break;
		case 'Z':
		    break;

	    }
    }
}

static VTSquare (char ch1)
{
    char *ptr;
    short pBuf[16];
    char Rbuf[16], *Rptr;
    int dval, nChar, i, j, ic, mc, nCol;
    char c;
    char qMark;
    short sv1, sv2;

    ptr = EscBuf + 1;
    if (*ptr == '?')
    {
	ptr++;
	qMark = 1;
    }
    else
    {
	qMark = 0;
    }

    dval = nChar = 0;
    while (*ptr)
    {
	c = *ptr++;
	if (c >= '0' && c <= '9')
	{
	    dval = dval * 10 + (c - '0');
	}
	else
	{
	    pBuf[nChar++] = dval;
	    dval = 0;
	}
    }
    pBuf[nChar] = 0;

    switch (ch1)
    {
	case 'H':
	case 'f':
	    if (pBuf[0])
	    {
		pBuf[0] -= 1;
	    }

	    if (pBuf[1])
	    {
		pBuf[1] -= 1;
	    }
	    if (RelOrg)
	    {
		pBuf[0] = SYtop + Ypos;
	    }
	    sd_pos (pChId, -1, (int) pBuf[1], (int) pBuf[0]);
	    break;

	case 'A':
	    i = (pBuf[0]) ? pBuf[0] : 1;
	    for (j = 0; (j < i && Ypos > SYtop); j++)
	    {
		sd_prow (pChId, -1);
		Ypos--;
	    }
	    break;
	case 'B':
	    i = (pBuf[0]) ? pBuf[0] : 1;
	    for (j = 0; (j < i && Ypos < SYbot); j++)
	    {
		sd_nrow (pChId, -1);
		Ypos++;
	    }

	    break;
	case 'C':

	    i = (pBuf[0]) ? pBuf[0] : 1;
	    if (__ANSICONF__.emulation & ANSI_M)
	    {
		NewPos (i);
	    }
	    else
	    {
		for (j = 0; j < i; j++)
		{
		    sd_ncol (pChId, -1);
		}
	    }
	    break;
	case 'D':
	    i = (pBuf[0]) ? pBuf[0] : 1;
	    if (__ANSICONF__.emulation & ANSI_M)
	    {
		NewPos (-i);
	    }
	    else
	    {
		for (j = 0; j < i; j++)
		{
		    sd_pcol (pChId, -1);
		}
	    }
	    break;

	case 'K':
	    switch (pBuf[0])
	    {
		case 0:
		    sd_clrrt (pChId, -1);
		    break;
		case 1:
		    ClearToCursor ();
		    break;
		case 2:
		default:
		    sd_clrln (pChId, -1);
		    break;
	    }
	    break;

	case 'J':
	    switch (pBuf[0])
	    {
		case 0:
		    sd_clrrt (pChId, -1);
		    sd_clrbt (pChId, -1);
		    break;
		case 1:
		    sd_clrtp (pChId, -1);
		    ClearToCursor ();
		    break;
		case 2:
		default:
		    sd_clear (pChId, -1);
		    break;
	    }
	    break;

	case 'L':
	case 'M':
	    sv1 = ReDef[1];
	    sv2 = ReDef[3];
	    ReDef[1] = (YINC) * (SYbot - Xpos + 1);
	    ReDef[3] = ConDef[3] + Xpos * (YINC);
	    j = (YINC) * ((pBuf[0]) ? pBuf[0] : 1);
	    if (ch1 == 'M')
	    {
		j = -j;
	    }
	    ScrollScreen (j);
	    ReDef[1] = sv1;
	    ReDef[3] = sv2;
	    break;

	case 'P':
	    j = -XINC * ((pBuf[0]) ? pBuf[0] : 1);
	    sd_pan (pChId, -1, j);
	    break;

	case 'm':
	    j = RCFlag ^ 1;
	    for (i = 0; i < nChar; i++)
	    {
		if (__ANSICONF__.emulation == VT100)
		{
		    switch (pBuf[i])
		    {
			case 0:
			    sd_setul (pChId, -1, 0);
			case 22:
			case 25:
			    Colour (pChId, (int) (bCol = NrmFCol[j]),
				    (int) (fCol = NrmFCol[RCFlag]));
			    break;
			case 1:
			    Colour (pChId, (int) (bCol = BoldCol[j]),
				    (int) (fCol = BoldCol[RCFlag]));
			    break;
			case 4:
			    sd_setul (pChId, -1, 1);
			    break;
			case 5:
			    Colour (pChId, (int) (bCol = FlashC[j]),
				    (int) (fCol = FlashC[RCFlag]));
			    break;
			case 7:
			    c = bCol;
			    bCol = fCol;
			    fCol = c;
			    Colour (pChId, (int) bCol, (int) fCol);
			    break;
		    }
		}
		else
		{
		    switch (pBuf[i])
		    {
			case 1:
			    if (__ANSICONF__.emulation & ANSI_BOLD)
			    {
				abold = 1;
			    }
			    break;
			case 0:
			    abold = 0;
			    Colour (pChId, (int) (bCol = NrmFCol[1]),
				    (int) (fCol = NrmFCol[0]));
			case 24:
			    sd_setul (pChId, -1, 0);
			    break;
			case 4:
			    sd_setul (pChId, -1, 1);
			    break;

			case 7:
			case 27:
			    c = bCol;
			    bCol = fCol;
			    fCol = c;
			    Colour (pChId, (int) bCol, (int) fCol);
			    break;
			case 39:
			    Colour (pChId, (int) bCol,
				    (int) (fCol = NrmFCol[0]));
			    break;
			case 49:
			    Colour (pChId, (int) (bCol = NrmFCol[1]),
				    (int) fCol);
			    break;
			default:
			    ic = pBuf[i] % 10;
			    mc = pBuf[i] / 10;
			    if (ic >= 0 && ic < 8)
			    {
				if (__ANSICONF__.emulation & ANSI_8COL)
				{
				    nCol = ANSITab[mc == 3 ? abold : 0][ic];
				}
				else
				{
				    nCol = (ic % 4) * 2;
				}
				if (mc == 3)
				{
				    if (abold && (__ANSICONF__.emulation == ANSI4))
				    {
					if (bCol != ANSIBold[ic])
					{
					    nCol = ANSIBold[ic];
					}
				    }
				    Colour (pChId, (int) bCol,
					    (int) (fCol = nCol));
				}
				if (mc == 4)
				{
				    Colour (pChId, (int) (bCol = nCol),
					    (int) fCol);
				}
			    }
			    break;
		    }
		}
	    }
	    break;

	case 'n':
	    break;
	case 'c':
	    break;
	case 'r':
	    if (pBuf[0])
	    {
		pBuf[0] -= 1;
	    }

	    SYtop = pBuf[0];
	    SYbot = (pBuf[1]) ? pBuf[1] - 1 : SYEnd;
	    if (SYtop == 0 && SYbot == SYEnd)
	    {
		bScroll = 0;
	    }
	    else
	    {
		bScroll = 1;
	    }
	    ReDef[1] = (YINC) * (SYbot - SYtop + 1);
	    ReDef[3] = ConDef[3] + SYtop * (YINC);
	    sd_pos (pChId, -1, 0, 0);
	    break;

	case 'l':
	case 'h':
	    if (qMark)
	    {
		switch (pBuf[0])
		{
		    case 1:
			break;

		    case 2:
			if (ch1 == 'l')
			{
			    VTInit (1);
			    __ANSICONF__.emulation = VT52;
			}
			break;
		    case 3:
			sd_clear (pChId, -1);
			sd_pos (pChId, -1, 0, 0);
			break;
		    case 4:
			jScroll = (ch1 == 'h') ? 0 : 10;
			break;
		    case 5:
			j = (ch1 == 'h') ? 1 : 0;
			if (j != RCFlag)
			{
			    RCFlag = j;
			    sd_recol (pChId, -1, ColorTab);
			    c = bCol;
			    bCol = fCol;
			    fCol = c;
			    Colour (pChId, (int) bCol, (int) fCol);
			    sd_setpa (pChId, -1, (int) bCol);
			}
			break;
		    case 6:
			RelOrg = (ch1 == 'h');
			break;

		    case 7:
			bWrap = (ch1 == 'h');
			break;

		    case 8:
			break;
		    case 25:
			if (ch1 == 'h')
			{
			    csr = 1;
			    sd_cure(pChId, -1);
			}
			else
			{
			    csr = 0;
			    sd_curs(pChId, -1);
			}
			break;
		}
	    }
	    else
	    {
		switch (pBuf[0])
		{
		    case 20:
			if (ch1 == 'h')
			{
			    bRXEOL = EOLCRLF;
			}
			else
			{
			    bRXEOL = EOLLF;
			}
			break;
		    case 4:
			bInsert = (ch1 == 'h');
			break;
		}
	    }
	    break;
	case 'g':
	    if (pBuf[0] == 0)
	    {
		RemTabList ();
	    }
	    else if (pBuf[0] == 3)
	    {
		nTab = 0;
	    }
	    break;
	case 's':
	    /* sXpos = Xpos;   sYpos = Ypos; */
	    SaveCursor ();
	    break;
	case 'u':
	    /*
	     * sd_pos (pChId, -1, (int) (Xpos = sXpos), (int) (Ypos =
	     * sYpos));
	     */
	    LoadCursor ();
	    break;
    }
}

static ClearToCursor (void)
{
    int i;
    int xp = Xpos;

    sd_tab (pChId, -1, 0);
    for (i = 0; i < xp; i++)
    {
	WriteChar (' ');
    }
}

static VTHash (char ch1)
{
    int i, j;
    int ch;

    switch (ch1)
    {
	case '3':
	    sd_setsz (pChId, -1, 2, 1);
	    sCount = 3;
	    break;
	case '4':
	    sCount = 0;
	    break;
	case '5':
	    sd_setsz (pChId, -1, 0, 0);
	    break;
	case '6':
	    sd_setsz (pChId, -1, 2, 0);
	    sCount = 3;
	    break;
	case '7':
	case '8':
	    sd_pos (pChId, -1, 0, 0);
	    for (ch = 'E', i = 0; i < (SYEnd+1); i++)
	    {
		for (j = 0; j < 80; j++)
		{
		    io_sbyte (pChId, -1, ch);
		    if (ch1 == '7')
		    {
			ch++;
			if (ch > 127)
			{
			    ch = 32;
			}
		    }
		}
		sd_nl (pChId, -1);
	    }
	    break;
    }
}

static NewLine (void)
{
    int xp;

    if (sCount & 2)
    {
	sd_setsz (pChId, -1, 0, 0);
    }
    sCount = 1;
    if (!bScroll)
    {
	int sts;

	sts = sd_nl (pChId, -1);
	if (sts < 0)
	{
	    if (jScroll)
	    {
		sd_scrol (pChId, -1, -jScroll * (YINC));
		sd_pos (pChId, -1, 0, SYEnd + 1 - jScroll);
	    }
	    else
	    {
		io_sbyte (pChId, -1, '\n');
		sd_donl (pChId, -1);
	    }
	}
	else
	{
	    sd_donl (pChId, -1);
	}
    }
    else
    {
	ReadCsr (pChId, &Xpos, &Ypos);
	xp = Xpos;
	if (Ypos >= SYbot)
	{
	    ScrollScreen (-(YINC));
	    sd_pos (pChId, -1, 0, (int) SYbot);
	    sd_clrln (pChId, -1);
	}
	else
	{
	    /* Can't imagine why it's done like this */
	    sd_pos (pChId, -1, 0, (int) Ypos);
	    sd_pos (pChId, -1, 0, (int) Ypos + 1);
	}
	Xpos = xp;
    }
    lastpr = LF;
}

static WriteChar (unsigned char ch)
{
    int req = 1;

    if (__ANSICONF__.emulation == VT100 && cSet[vtMode] == C_GRAF)
    {
	if (ch > '_' && ch < 127)
	{
	    req = 3;
	}
    }

    if (req == 3)
    {
        sd_fount (pChId, -1, _DECGraf_, NULL);        
    }
    if (ch > 31 || ((__ANSICONF__.emulation & ANSI_M) && ch))
    {
	if (bInsert && ch > 31 || bWrap == 0)
	{
	    if (bWrap == 0)
	    {
		ReadCsr (pChId, &Xpos, &Ypos);
		if (Xpos >= 79)
		{
		    req = 0;
		    io_sbyte (pChId, -1, (char) '¹');
		    sd_pos (pChId, -1, (int) Xpos, (int) Ypos);
		}
	    }
	    else
	    {
		sd_pan (pChId, -1, XINC);
	    }
	}
	if (req)
	{
	    io_sbyte (pChId, -1, (char) ch);
	}
    }
    if (req & 2)
    {
	sd_fount (pChId, -1, NULL, NULL);
    }
    lastpr = ch;
}

static NextTabStop (void)
{
    int nt;
    int i;

    ReadCsr (pChId, &Xpos, &Ypos);
    if (__ANSICONF__.emulation & VT100_M)
    {
	nt = 79;
	for (i = 0; i < nTab; i++)
	{
	    if (TabBuf[i] > Xpos)
	    {
		nt = TabBuf[i];
		break;
	    }
	}
    }
    else
    {
	nt = (Xpos - (Xpos % 8)) + 8;
	if (nt > 79)
	{
	    nt = 79;
	}
    }

    sd_pos (pChId, -1, nt, (int) Ypos);
}

static AddTabList (void)
{
    int i, k = 0;

    for (i = 0; i < nTab; i++)
    {
	if (TabBuf[i] < Xpos)
	{
	    break;
	}
    }
    nTab++;
    k = i;
    for (i = nTab; i > k;)
    {
	TabBuf[i] = TabBuf[--i];
    }
    TabBuf[k] = Xpos;
}

static RemTabList ()
{
    int i, k;

    for (i = 0; i < nTab; i++)
    {
	if (TabBuf[i] == Xpos)
	{
	    break;
	}
    }
    if (i != nTab)
    {
	for (k = i; k < nTab;)
	{
	    TabBuf[k] = TabBuf[++k];
	}
	nTab--;
    }
}

static ScrollTop (void)
{
    ReadCsr (pChId, &Xpos, &Ypos);
    if (Ypos != SYtop)
    {
	sd_prow (pChId, -1);
    }
    else
    {
	ScrollScreen (YINC);
	sd_pos (pChId, -1, (int) Xpos, (int) SYtop);
	sd_clrln (pChId, -1);
    }
}

static ScrollScreen (int dirn)
{
    sd_wdef (pChId, -1, 0, 0, (struct QLRECT *) ReDef);
    sd_scrol (pChId, -1, dirn);
    sd_wdef (pChId, -1, 0, 0, (struct QLRECT *) ConDef);
}

static NewPos (int apos)
{
    int pos;

    pos = Ypos * 80 + Xpos + apos;
    if (pos < 0)
    {
	Xpos = Ypos = 0;
    }
    else if (pos >= 80*(SYEnd + 1))
    {
	Xpos = 79;
	Ypos = SYEnd;
    }
    else
    {
	Xpos = pos % 80;
	Ypos = pos / 80;
    }
    sd_pos (pChId, -1, Xpos, Ypos);
}
static Colour (int chan, int bcol, int fcol)
{
    sd_setin (chan, -1, fcol);
    sd_setst (chan, -1, bcol);
}

static VT52Esc (char ch)
{
    *pEscBuf++ = ch;
    if (ch == 'Y')
    {
	sState = SESCP1;
    }
    else
    {
	sState = SESCEX;
    }
}

static AddEscBuffer (char ch)
{
    if (ch == CAN || ch == SS || ch == ESC)
    {
	CanSub (ch);
    }
    else
    {
	*pEscBuf++ = ch;

	switch (sState)
	{
	    case SESCNO:
	    case SESCGx:
		sState = SESCEX;
		break;

	    case SESCP1:
		sState = SESCP2;
		break;

	    case SESCP2:
		sState = SESCEX;
		break;

	    case SESCPM:
		if (ch > 63)
		{
		    sState = SESCEX;
		}
		break;
	}
    }
}

static DoEscSeq (void)
{
    *pEscBuf = '\0';
    if (__ANSICONF__.emulation == VT52)
    {
	switch (EscBuf[0])
	{
	    case 'A':
		sd_prow (pChId, -1);
		break;
	    case 'B':
		sd_nrow (pChId, -1);
		break;
	    case 'C':
		sd_ncol (pChId, -1);
		break;
	    case 'D':
		sd_pcol (pChId, -1);
		break;
	    case 'F':
		vtMode = 1;
		break;
	    case 'G':
		vtMode = 0;
		break;
	    case 'H':
		sd_pos (pChId, -1, 0, 0);
		break;
	    case 'I':
		ScrollTop ();
		break;
	    case 'J':
		sd_clrrt (pChId, -1);
		sd_clrbt (pChId, -1);
		break;
	    case 'K':
		sd_clrln (pChId, -1);
		break;
	    case 'U':
		break;
	    case 'W':
		break;
	    case 'X':
		break;
	    case 'Y':
		sd_pos (pChId, -1, EscBuf[2] - 32, EscBuf[1] - 32);
		break;
	    case 'Z':
		break;
	    case '=':
	    case '>':
		break;
	    case '<':
		__ANSICONF__.emulation = VT100;
		VTInit (1);
		break;
	    case '^':
	    case '_':
	    case ']':
		break;
	}
    }
    else
    {
	EscVT100 ();
    }
    sState = SNORM;
}

static ProcessNorm (unsigned char ch)
{
    if (bCR == TRUE)
    {
	if (ch != LF)
	{
	    sd_tab (pChId, -1, 0);
	}
	bCR = FALSE;
    }

    if (ch > 31)
    {
	if (sCount & 1)
	{
	    if (ch == 0x9B && (__ANSICONF__.emulation & ANSI_M)
                            && __ANSICONF__.csi == 0)
	    {
		pEscBuf = EscBuf;
		VT100Esc ('[');
	    }
	    else
	    {
		if (ch == 96 && (__ANSICONF__.emulation & VT100_M))
		{
		    ch = 39;
		}
		WriteChar (ch);
	    }
	}
    }
    else
    {
	switch (ch)
	{

	    case ESC:
		sState = SESC;
		pEscBuf = EscBuf;
		break;

	    case BS:
		sd_pcol (pChId, -1);
		break;

            case '\a':
		beep (1200, 5);
		break;

	    case TAB:
		NextTabStop ();
		break;

	    case CR:
		if (bRXEOL == EOLCR)
		{
		    NewLine ();
		}
		else
		{
		    bCR = TRUE;
		}
		break;

	    case SO:
		vtMode = 1;
		break;

	    case SI:
		vtMode = 0;
		break;

	    case LF:
		if (bRXEOL == EOLLF || (bRXEOL == EOLCRLF && lastch == CR))
		{
		    NewLine ();
		}
		else
		{
		    ReadCsr (pChId, &Xpos, &Ypos);
		    NewLine ();
		    sd_tab (pChId, -1, Xpos);
		}
		break;

	    case VT:
		sd_prow (pChId, -1);
		break;
	    case FF:
		sd_pos (pChId, -1, 0, 0);
		sd_clear (pChId, -1);
		break;
	    default:
		if (__ANSICONF__.emulation & ANSI_M)
		{
		    sd_fount (pChId, -1, _ANSICtl_, _ANSIChr_);
		    WriteChar (ch);
		    sd_fount (pChId, -1, NULL, _ANSIChr_);
		}
		else
		{
		    WriteChar (ch);
		}
		break;
	}
    }
    lastch = ch;
}
static CanSub (char ch)
{
    sState = SNORM;
    if (ch == SS)
    {
	io_sbyte (pChId, -1, (char) 0xb4);
    }
}
ReadCsr (int pChId, short *pXpos, short *pYpos)
{
    struct QLRECT rct;

    sd_chenq(pChId, -1, &rct);
    *pXpos = rct.q_x;
    *pYpos = rct.q_y;
}
