/*->c.mxterm */

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <signal.h>
#include <ctype.h>
#include <time.h>

#include "h.os"
#include "h.wimp"
#include "h.bbc"
#include "h.flex"


#include "h.wos"
#include "h.main"
#include "h.ram"
#include "h.mym"
#include "h.def"


#include "h.term"

#include "h.replay"

#include "h.vtdef"
#include "h.vtwimp"
#include "h.vtfile"
#include "h.vtscr"

#include "h.vxdef"
#include "h.vxwimp"
#include "h.vxcol"
#include "h.vxsend"
#include "h.vxterm"
#include "h.vxbuff"

#include "h.xext"

#include "h.mxterm"


/***************************************************************************/
/*
 Code for Minitel Terminal
*/
/*****************************************************************************/

#define MXHIDE   0x80000000

#define MXCNC    0x01000000
#define MXFLASH1 0x02000000
#define MXFLASH2 0x04000000

#define MXUNDER  0x00800000
#define MXDW     0x00400000
#define MXDH     0x00200000
#define MXFCOL   0x00003800            /* was 0x7800  */
#define MXFCOLS  11
#define MXBCOL   0x00070000            /* was 0xF0000 */
#define MXBCOLS  16

#define MXINV    0x00100000

#define MXCHAR   0x000001FF


#define MXGRSPC  145
#define MXSPC    506
#define MXGSTART 353


int minitel;

int mxscroll;                   /* global scroll mode?    */
int mxcnc;                      /* global concealed mode? */



int mxset;                      /* G0, G1, G2, G3 */

int mxlatent;

int mxforeground;
int mxbackground;
int mxstyle;


int mxrealcnc;
int mxrealul;

int mxbackgroundl;
int mxpendcnc;
int mxpendul;


int mxss2;
int mxss2first;
int mxmodded;


int mxapa;                      /* APA seq */
int mxapax;
int mxrep;                      /* REP seq */
int mxlast;
int mxesc;
int mxesc1;
int mxtrans;
int mxsink1;


char mxisomap[MXMAPSIZE]=
{
         0,
         1,
         2,
         3,
         4,
         5,
         6,
         7,
         8,
         9,
        10,
        11,
        12,
        13,
        14,
        15,
        16,
        17,
        18,
        19,
        20,
        21,
        22,
        23,
        24,
        25,
        26,
        27,
        28,
        29,
        30,
        31,
        32,
        33,
        34,
       163,
        36,
        37,
        38,
        39,
        40,
        41,
        42,
        43,
        44,
        45,
        46,
        47,
        48,
        49,
        50,
        51,
        52,
        53,
        54,
        55,
        56,
        57,
        58,
        59,
        60,
        61,
        62,
        63,
        64,
        65,
        66,
        67,
        68,
        69,
        70,
        71,
        72,
        73,
        74,
        75,
        76,
        77,
        78,
        79,
        80,
        81,
        82,
        83,
        84,
        85,
        86,
        87,
        88,
        89,
        90,
        32,
       189,
        32,
        32,
        35,
       152,
        97,
        98,
        99,
       100,
       101,
       102,
       103,
       104,
       105,
       106,
       107,
       108,
       109,
       110,
       111,
       112,
       113,
       114,
       115,
       116,
       117,
       118,
       119,
       120,
       121,
       122,
       188,
       124,
       190,
       247,
        32,
        32,
        32,
       152,
       139,
       138,
       137,
       136,
        95,
        32,
        32,
        93,
        91,
        32,
        32,
        32,
       154,
       155,
       177,
       176,
       161,
       162,
       165,
       167,
       164,
       144,
       148,
       171,
       136,
       139,
       137,
       138,
       178,
       179,
       215,
       181,
       182,
       183,
       145,
       149,
       187,
       191,
        96,
       180,
        94,
       126,
       175,
        32,
        32,
       168,
        32,
       176,
       184,
        32,
        32,
        32,
       185,
       175,
       169,
       141,
        32,
        32,
        32,
        32,
        32,
        32,
       198,
       208,
       170,
        32,
        32,
        32,
        32,
       216,
       186,
       222,
        32,
        32,
        32,
        75,
       230,
        32,
       240,
        32,
        32,
        32,
        32,
        32,
       248,
       223,
       254,
        32,
        32,
        92,
       124,
        94,
       123,
       125,
        96,
        32,
       224,
       226,
       249,
       233,
       232,
       234,
       238,
       239,
       231,
       194,
       201,
       200,
       206,
       244,
       251,
       199,
       244,
       251,
       252,
       220,
       246,
       214,
       228,
        32,
        32,
        32,
        32,
        32,
       225,
       193,
       192,
       227,
       195,
        32,
        32,
       229,
       197,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
       202,
       235,
       203,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
       237,
       205,
       236,
       204,
       207,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
       237,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
       241,
       209,
        32,
        32,
        32,
        32,
       243,
       211,
       242,
       210,
       245,
       213,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
       250,
       218,
       217,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
       130,
       129,
       253,
       221,
        32,
       133,
       255,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
        32,
};


/* void setmxisomap(int index,int mapto); 0<=index<=(512+32) */

void setmxisomap(int fp)
{
 int index;
 int mapto;

 index=stack[fp];
 mapto=stack[fp+1];

 mxisomap[index]=mapto;
}


/*****************************************************************************/



static int dlcc[8]=
{
 0x00000000,
 0x17171717,
 0x63636363,
 0x77777777,
 0x8B8B8B8B,
 0x9F9F9F9F,
 0xEBEBEBEB,
 0xFFFFFFFF
};


void mxinitblock(vxscreen * vscr)
{
 int i;

 for(i=0;i<25;i++) vscr->u.cept2.back[i]=0x3800;
 for(i=0;i<8;i++)  vscr->u.cept2.look1[i]=dlcc[i];
 for(i=0;i<8;i++)  vscr->u.cept2.look2[i]=dlcc[i];
 vscr->u.cept2.dynam=0x03020100;
 vscr->u.cept2.flags=0;
 vscr->u.cept2.attr=(1<<10)+(1<<29);
 vscr->u.cept2.parallel=0x083800;
 vscr->u.cept2.sbrk=0;
 vscr->u.cept2.lastchar=0;
 vscr->u.cept2.lastcharl=0;
 vscr->u.cept2.zero1=0;     
 for(i=0;i<8;i++)  vscr->u.cept2.zero5[5]=0;
 vscr->u.cept2.x=0;
 vscr->u.cept2.y=0;
 vscr->u.cept2.g0=0x40;
 vscr->u.cept2.g1=0x63;
 vscr->u.cept2.g2=0x62;
 vscr->u.cept2.g3=0x64;
 vscr->u.cept2.glr=0x80;
 vscr->u.cept2.zero2=0;
 vscr->u.cept2.zero3=0;
 vscr->u.cept2.tops=0;
 vscr->u.cept2.bots=0;      
 for(i=0;i<8;i++)  vscr->u.cept2.stuff[11]=0;
}



void vxinitblock(vxscreen * vscr)
{
 int i;

 if(minitel) mxinitblock(vscr);
 else        for(i=0;i<64;i++) vscr->u.cept3.route[i]=0;
}




void mxsetflash(vxscreen * vscr,int y)
{
 int * vpoint;
 int   x;

 vscr->flo[y]=vscr->fhi[y]=0;
 vpoint=&(vscr->tvbuf[y][0]);

 for(x=0;x<40;x++)
 {
  if((*vpoint) & (VXFLASH1+VXFLASH2))
  {
   if(vscr->flo[y]==vscr->fhi[y])
   {
    vscr->flo[y]=x;
    vscr->fhi[y]=x+1;
   }
   else
   if(x>=vscr->fhi[y])
   {
    vscr->fhi[y]=x+1;
   }
  }
  vpoint++;
 }
}




/*****************************************************************************/


/* takes line y and maps cbuf into vbuf */

void mxconvertline(vxscreen * vscr,int y) 
{ 
 int    curxl;
 int    curxh;

 int  * vpoint;
 int  * cpoint;
 int  * pvpoint;
 int  * pcpoint;
 int    code;
 int    byte;

 int    x;

 int    pend;

                        /* running variables */
 int    f;              /* foreground colour */
 int    b;              /* background colour */
 int    conceal;        /* conceal           */
 int    uline;          /* lining for text   */
 int    style;          /* style             */
 int    lastchar;       /* 0==nothing, 1==field delim, 2==graph, 3==alpha */
 int    dble;
 int    value;

 vpoint=&(vscr->tvbuf[y][0]);
 if(y>1)
 {
  pvpoint=&(vscr->tvbuf[y-1][0]);
  pcpoint=&(vscr->tcbuf[y-1][0]);
 }
 else pvpoint=pcpoint=NULL;

 cpoint=&(vscr->tcbuf[y][0]);
 curxl=0;
 curxh=40;

 pend=0;


 f=WHITE;
 b=BLACK;
 style=vxfindcolours(f,b,0);
 conceal=0;
 uline=0;
 lastchar=0;


 for(x=0;x<40;x++)
 {
  dble=(pcpoint && ((*pcpoint) & MXDH));

  code=*cpoint;
  byte=code & MXCHAR;

  if(byte==MXSPC)
   {               /* this is a field delimiter */
                   /* char level can be background colour */
                   /* and concealing */

    if(lastchar==2) uline=0;
    style=0;

    if(code & MXCNC)   conceal=1;
    else               conceal=0;

    if(code & MXUNDER) uline=1;
    else               uline=0;

    if(code & MXDW) style|=VXDWL;

    if(dble)        style|=VXDHB;
    else
    if(code & MXDH) style|=VXDHT;

    if(code & MXINV)
    {
     f=(code & MXBCOL)>>MXBCOLS;
     b=(code & MXFCOL)>>MXFCOLS;
     style=vxfindcolours(b,f,style);
    }
    else
    {
     f=(code & MXFCOL)>>MXFCOLS;
     b=(code & MXBCOL)>>MXBCOLS;
     style=vxfindcolours(f,b,style);
    }
    lastchar=1;
   }
  else
  if(byte>=MXGSTART || byte==MXGRSPC)
   {               /* graphics char */
                   /* char level fcol, flash, bcol, sep */

    f=(code & MXFCOL)>>MXFCOLS;
    b=(code & MXBCOL)>>MXBCOLS;

    style=vxfindcolours(f,b,0);

    if(code & MXFLASH1)  style|=VXFLASH1;
    if(code & MXFLASH2)  style|=VXFLASH2;
    if((code & MXUNDER) && byte!=MXGRSPC) style|=VXUNDER;
    if(mxcnc && conceal) byte=0;
    lastchar=2;
   }
  else
   {              /* alpha char */
                  /* char level fcol, flash, height, width, polarity */

    if(lastchar==2) uline=0;
    style=0;

    if(code & MXDW) style|=VXDWL;

    if(code & MXDH) style|=VXDHT;

    if(code & MXINV)
    {
     f=(code & MXBCOL)>>MXBCOLS;
     style=vxfindcolours(b,f,style);
     *cpoint=((*cpoint) & (~MXFCOL))|(b<<MXFCOLS);
    }
    else
    {
     f=(code & MXFCOL)>>MXFCOLS;
     style=vxfindcolours(f,b,style);
     *cpoint=((*cpoint) & (~MXBCOL))|(b<<MXBCOLS);
    }

    if(code & MXFLASH1)  style|=VXFLASH1;
    if(code & MXFLASH2)  style|=VXFLASH2;

    if(byte==(127-32)) byte=96;
    else
    if(uline) style|=VXUNDER;

    if(mxcnc && conceal) byte=0;
    lastchar=3;
   }

  if(pend==1) value=value ^ (VXDWL|VXDWR);
  else
  if(dble)    value=(*pvpoint) ^ (VXDHT|VXDHB);
  else        value=byte+style;

  if(value & VXDWL) pend=1;
  else              pend=0;

  if(*vpoint==value)
  {
   if(curxh==40) curxl=x;
  }
  else
  {
   curxh=x;
   *vpoint=value;
  }

  cpoint++;
  vpoint++;
  if(pvpoint)
  {
   pvpoint++;
   pcpoint++;
  }
 }

 if(curxh!=40)
 {
  mxsetflash(vscr,y);
  vxmarkredraw(vscr,y,curxl,curxh);
 }
}



/* convert anything we have changed */

void mxconvert(vxscreen * vsc)
{
 int i;

 for(i=0;i<25;i++)
 {
  if(vsc->lmod[i])
  {
   mxconvertline(vsc,i); 
   vsc->lmod[i]=0;
  }
 }
 mxmodded=0;
}


/* force conversion on all lines */

void mxconvertall(vxscreen * vsc)
{
 int i;

 for(i=0;i<25;i++) vsc->lmod[i]=1;
 mxconvert(vsc);
}


/*****************************************************************************/


void mxsetstylec(void)
{
 int b;
 int f;

 if(mxstyle & MXINV)
 {
  b=mxforeground;
  f=mxbackground;
 }
 else
 {
  b=mxbackground;
  f=mxforeground;
 }

 mxstyle&=~(MXBCOL|MXFCOL);
 mxstyle|=(f<<MXFCOLS)+(b<<MXBCOLS);
}



void mxreset(void)
{
 mxforeground=WHITE;
 mxbackground=mxbackgroundl=BLACK;
 mxstyle=0;
 mxsetstylec();

 mxset=0;
 mxscroll=0;
 mxcnc=1;

 mxlatent=0;
 mxpendcnc=mxpendul=0;
 mxrealcnc=mxrealul=0;

 mxapa=0;
 mxesc=0;
 mxrep=0;
 mxtrans=0;
 mxsink1=0;
}



void mxvalidate(void)
{
 mxbackground=mxbackgroundl;
 mxrealcnc=mxpendcnc;
 mxrealul=mxpendul;
 mxlatent=0;
 mxsetstylec();
}


void mxvalidategr(void)
{
 mxbackground=mxbackgroundl;
 mxsetstylec();
}


/* used on Home and Tab */

void mxdefltcols(void)
{
 mxbackgroundl=mxbackground=BLACK;
 mxlatent=0;
 mxpendcnc=mxpendul=0;
 mxrealcnc=mxrealul=0;

 mxforeground=WHITE;
 mxstyle=0;
 mxsetstylec();
 mxset=0;
}


/*****************************************************************************/


void mxclrrow(vxscreen * vsc,int y)
{
 int x;

 int front=vxphysicalcolour(WHITE);
 int back=vxphysicalcolour(BLACK);
 int colours;

 front=front ^ back;

 colours=(front<<24)+(back<<16);

 vsc->rlo[y]=vsc->rhi[y]=0;
 vsc->flo[y]=vsc->fhi[y]=0;
 vsc->attr[y]=VXASH;
 vsc->lmod[y]=1;
 for(x=0;x<40;x++)
 {
  vsc->tcbuf[y][x]=MXGRSPC;
  vsc->tvbuf[y][x]=MXGRSPC+colours;
 }

 mxmodded=1;
} 



void mxclslo(vxscreen * vsc)
{
 int y;

 for(y=0;y<vsc->height;y++) mxclrrow(vsc,y);

 ttvx=0;
 ttvy=1;
}



void mxcls(void)
{
 int y;

 if(replayfix)
 {
  replayclscode=MXCLS;
  return;
 }

 mxclslo(vscr);
 for(y=0;y<vscr->height;y++)
 {
  vscr->rhi[y]=40;
  vscr->rlo[y]=0;
  vscr->lmod[y]=0;
  vxpendredraw=1;
 }
}



void mxrefresh(void)
{
 int y;
 for(y=0;y<vscr->height;y++) vscr->lmod[y]=1;
}



void mxconceal(void)
{
 mxcnc=1;
 mxrefresh();

/* dprintf(0,"conceal"); */
}



void mxreveal(void)
{
 mxcnc=0;
 mxrefresh();

/* dprintf(0,"reveal");  */
}


/*****************************************************************************/

char g2map[96]=
{
   0,
 115,
 116,
   3,
   4,
 117,
  63,
 118,
 119,
 120,
 121,
 122,
 123,
 124,
 125,
 126,
 114,
 113,
 127,
 128,
 129,
 130,
 131,
 132,
  94,
 133,
 134,
 135,
  91,
  60,
  93,
 136,
   0,  /* 64, ' sequences */
 137,
 138,
 139,
 140,
 141,
 142,
 143,
 144,
   0,
 146,
 147,
   0,
 148,
 149,
 150,
  98,
 151,
 152,
 153,
 154,
 155,
   0,
   0,
   0,
   0,
   0,
   0,
 156,
 157,
 158,
 159,
 160,
 161,
 162,
 163,
 164,
   0,
 165,
 166,
 167,
 168,
 111,
 169,
 170,
 171,
 172,
 173,
 174,
 175,
 176,
 177,
 178,
 179,
 180,
 181,
 182,
 183,
 112,
 184,
 185,
 186,
 187,
  96
};





typedef struct g2cc 
{
 char      let;
 short int code;
} g2cc;





#define G2INX0   0
#define G2INX1   G2INX0+1
#define G2INX2   G2INX1+12
#define G2INX3   G2INX2+22
#define G2INX4   G2INX3+24
#define G2INX5   G2INX4+12
#define G2INX6   G2INX5+12
#define G2INX7   G2INX6+18
#define G2INX8   G2INX7+11
#define G2INX9   G2INX8+9
#define G2INX10  G2INX9+1
#define G2INX11  G2INX10+6
#define G2INX12  G2INX11+19
#define G2INX13  G2INX12+1
#define G2INX14  G2INX13+6
#define G2INX15  G2INX14+10
#define G2INX16  G2INX15+21





g2cc g2cctab[G2INX16]=
{
 0,0,                    /* 64 - 1 */


 SPC,137,                /* 65 - 12 */
 'a',195,
 'u',197,
 'e',199,
 'E',206,
 'A',225,
 'i',269,
 'I',270,
 'o',299,
 'O',300,
 'n',173,
   0,0,

                         /* 66 -  22 */
 SPC,138,
 'e',198,
 'E',205,
 'a',223,
 'c',236,
 'C',237,
 'g',257,
 'i',267,
 'I',268,
 'l',283,
 'L',284,
 'n',289,
 'N',290,
 'o',297,
 'O',298,
 'r',307,
 'R',308,
 's',313,
 'S',314,
 'u',325,
 'U',326,
   0,0,

                         /* 67 -  24   */
 SPC,139,
 'a',196,
 'e',200,
 'i',201,
 'A',204,
 'I',207,
 'O',208,
 'U',209,
 'o',211,
 'u',212,
 'c',238,
 'C',239,
 'E',246,
 'g',258,
 'G',259,
 'h',265,
 'H',266,
 's',315,
 'S',316,
 'w',340,
 'W',341,
 'y',344,
 'Y',345,
   0,0,


                   /*68 - 12 */
 SPC,140,
 'a',226,
 'A',227,
 'i',272,
 'I',273,
 'n',291,
 'N',292,
 'o',301,
 'O',302,
 'u',328,
 'U',329,
   0,0,

                   /* 69 - 12 */
 SPC,141,
 'a',232,
 'A',233,
 'e',253,
 'E',254,
 'i',275,
 'I',276,
 'o',305,
 'O',306,
 'u',336,
 'U',337,
   0,0,

                  /* 70 - 8 */
 SPC,142,
 'a',228,
 'A',229,
 'g',260,
 'G',261,
 'u',330,
 'U',331,
   0,0,

                  /* 71 - 11 */
 SPC,143,
 'Z',194,
 'c',242,
 'C',243,
 'e',251,
 'E',252,
 'g',262,
 'G',263,
 'I',274,
 'z',352,
   0,0,
                  /* 72 - 9 */

 SPC,144,
 'i',202,
 'u',213,
 'U',214,
 'o',215,
 'I',271,
 'y',346,
 'Y',347,
   0,0,


                /* 73  -  1     145   */
   0,0,

                /* 74  -  6     146  */

 SPC,146,
 'a',230,
 'A',231,
 'u',334,
 'U',335,
   0,0,

                /* 75  -  19     147  */
 SPC,147,
 'c',203,
 'C',210,
 'G',264,
 'k',281,
 'K',282,
 'l',287,
 'L',288,
 'n',295,
 'N',296,
 'r',311,
 'R',312,
 's',319,
 'S',320,
 't',323,
 'T',324,
 'u',338,
 'U',339,
   0,0,


                /* 76  -  1     SPC   */
   0,0,

                /* 77  -  6     148 */


 SPC,148,
 'o',303,
 'O',304,
 'u',332,
 'U',333,
   0,0,

                /* 78  -  10     149 */ 
 SPC,149,
 'a',234,
 'A',235,
 'e',255,
 'E',256,
 'i',277,
 'I',278,
 'k',281,
 'K',282,
   0,0,

                /* 79  -  21     150 */
 SPC,150,
 'A',218,
 'c',240,
 'C',241,
 'd',244,
 'D',245,
 'e',249,
 'E',250,
 'l',285,
 'L',286,
 'n',293,
 'N',294,
 'r',309,
 'R',310,
 's',317,
 'S',318,
 't',321,
 'T',322,
 'z',350,
 'Z',351,
   0,0
};




int g2index[16]=
{
 G2INX0,
 G2INX1,
 G2INX2,
 G2INX3,
 G2INX4,
 G2INX5,
 G2INX6,
 G2INX7, 
 G2INX8,
 G2INX9,
 G2INX10, 
 G2INX11,
 G2INX12, 
 G2INX13, 
 G2INX14, 
 G2INX15,
};



int mxg2cc(int byte,int mxss2first)
{
 int index;

 index=mxss2first-64;
 index=g2index[index];

 do
 {
  if(g2cctab[index].code==0) break;

  if(g2cctab[index].let==byte)
  {
   byte=g2cctab[index].code+32;
   break;
  }
  index++;
 } while(1);
 
 return(byte);
}




/* given a byte 32 to 127 and a set G0, G1, G2 */
/* return code to write */

int mxgmap(int byte,int set)
{
 if(set==1)
 {
  if(byte==127)            byte=0x5F; 

  if(byte==32)             byte=MXGRSPC+32;
  else
  if(byte<64 && byte>32)   byte=byte-32+352+32;
  else
  if(byte>=64 && byte<95)  byte=byte-64+416+32;
  else
  if(byte>=95 && byte<127) byte=byte-95+415+32;
 }
 else
 if(set==0)
 {
  if(byte==35) byte=63+32;
  else
  if(byte==47) byte=109+32;
  else
  if(byte==91) byte=107+32;
  else
  if(byte==92) byte=108+32;
  else
  if(byte==93) byte=106+32;
  else
  if(byte==95) byte=103+32;
  else
  if(byte==96) byte=98+32;
  else
  if(byte==123) byte=104+32;
  else
  if(byte==124) byte=110+32;
  else
  if(byte==125) byte=105+32;
  else
  if(byte==126) byte=97+32;
 }
 else
 if(set==2)
 {
  if(byte==127) byte=0x5F;

  byte=g2map[byte-32]+32;
 }

 return(byte);
}




/*****************************************************************************/


/* delta= +/- 1 */

void mxscrollmem(int delta,vxscreen * vsc)
{
 int n;
 int from;
 int to;
 int y;
 int i;


 if(delta>0)    /* scrolling up,  delta is +ve */
 {
                /* n rows to shift - from to 24 */
  n=vsc->height-vsc->start-delta;
  from=vsc->start+delta;
  to=vsc->start;
  memmove(&vsc->tcbuf[to][0],&vsc->tcbuf[from][0],n*40*sizeof(int));
  memmove(&vsc->tvbuf[to][0],&vsc->tvbuf[from][0],n*40*sizeof(int));

  for(i=to;i<(to+n);i++)
  {
   vsc->rlo[i]=vsc->rlo[i+delta];
   vsc->rhi[i]=vsc->rhi[i+delta];
   vsc->flo[i]=vsc->flo[i+delta];
   vsc->fhi[i]=vsc->fhi[i+delta];
   vsc->attr[i]=vsc->attr[i+delta];
   vsc->lmod[i]=vsc->lmod[i+delta];
  }

  for(y=n+1;y<vsc->height;y++) mxclrrow(vsc,y);
 }
 else           /* scrolling down,  delta is -ve */
 {
  n=vsc->height-vsc->start+delta;
  to=-delta+vsc->start;
  from=vsc->start;
  memmove(&vsc->tcbuf[to][0],&vsc->tcbuf[from][0],n*40*sizeof(int));
  memmove(&vsc->tvbuf[to][0],&vsc->tvbuf[from][0],n*40*sizeof(int));

  for(i=(to+n-1);i>=to;i--)
  {
   vsc->rlo[i]=vsc->rlo[i+delta];
   vsc->rhi[i]=vsc->rhi[i+delta];
   vsc->flo[i]=vsc->flo[i+delta];
   vsc->fhi[i]=vsc->fhi[i+delta];
   vsc->attr[i]=vsc->attr[i+delta];
   vsc->lmod[i]=vsc->lmod[i+delta];
  }

  for(y=vsc->start;y<to;y++) mxclrrow(vsc,y);
 }
}


#define NLINE 0x0

void mxscrollwin(int delta,vxscreen * vsc)
{
 int ox0;
 int ox1;
 int oy0;
 int oy1;

 int ny0;

 int sy0;
 int sy1;

 wimp_box box;
 wimp_redrawstr redrawstr;
 int  more;

 int  dshift;
 int  shift;


 shift=delta*VXDY;
 dshift=-shift;

 sy0=-vsc->height*VXDY;
 sy1=-vsc->start*VXDY;

 getw(whandle[VDATA]);

 ox0=x0-bx;
 ox1=x1-bx;
 oy0=y0-by;
 oy1=y1-by;

 if(sy1<oy0 || sy0>oy1) shift=0;  /* scroll zone is out of window */

 while(shift)
 {
  if(shift>(-dshift) && (shift+2*dshift)<0) dshift=-shift;
  else
  if(shift<(-dshift) && (shift+2*dshift)>0) dshift=-shift;

  if(dshift>0)     /* scroll down */
  {
   box.x0=ox0;
   box.x1=ox1;

   if(dshift<(sy1-sy0))
   {
    ny0=sy0;
    box.y0=sy0+dshift;
    box.y1=sy1;
    wimp_blockcopy(whandle[VDATA],&box,ox0,ny0);
    redrawstr.box.y0=sy1-dshift;
    redrawstr.box.y1=sy1;
   }
   else
   {
    redrawstr.box.y0=sy0;
    redrawstr.box.y1=sy1;
   }

   redrawstr.w=whandle[VDATA];
   redrawstr.box.x0=ox0;
   redrawstr.box.x1=ox1;
  }
  else             /* scroll up */
  {
   box.x0=ox0;
   box.x1=ox1;

   if(dshift>(sy0-sy1))
   {
    ny0=sy0-dshift;
    box.y0=sy0;
    box.y1=sy1+dshift;
    wimp_blockcopy(whandle[VDATA],&box,ox0,ny0);
    redrawstr.box.y0=sy0;
    redrawstr.box.y1=sy0-dshift;
   }
   else
   {
    redrawstr.box.y0=sy0;
    redrawstr.box.y1=sy1;
   }

   redrawstr.w=whandle[VDATA];
   redrawstr.box.x0=ox0;
   redrawstr.box.x1=ox1;
  }

  wimp_update_wind(&redrawstr,&more);
  while(more)
  {
   redrawvxsub(&redrawstr,NLINE,vsc);
   wimp_get_rectangle(&redrawstr,&more);
  }

  shift+=dshift;
 }
}



void mxscrollscreen(int delta,vxscreen * vsc)
{
 mxscrollmem(delta,vsc);
 mxscrollwin(delta,vsc);
}


void mxleavestatusline(void)
{





}


void mxenterstatusline(void)
{


 /* clear things */

 mxstyle&=~(MXDH|MXDW);
}


void mxdown(void)
{
 vxsetcursor();

 if(ttvy>0)
 {
  if(++ttvy==vscr->height)
  {
   if(mxscroll)
   {
    ttvy=vscr->height-1; /* 23 */
    mxscrollscreen(1,vscr);
   }
   else ttvy=1;
  }
 }
 else
 {
  mxleavestatusline();
  ttvy=1;
 }
}


void mxcrlf(void)
{
 vxsetcursor();

 if(ttvy>0)
 {
  if(++ttvy==vscr->height)
  {
   if(mxscroll)
   {
    ttvy=vscr->height-1; /* 23 */
    mxscrollscreen(1,vscr);
   }
   else ttvy=1;
  }
  ttvx=0;
 }
 else
 {
  ttvy=1;     /* a lot more */
  ttvx=0;
 }
}


void mxup(void)
{
 vxsetcursor();

 if(ttvy>0)
 {
  if(--ttvy==0)
  {
   if(mxscroll)
   {
    ttvy=1;
    mxscrollscreen(-1,vscr);
   }
   else ttvy=vscr->height-1; /* 23 */
  }
 }
}


void mxright(void)
{
 vxsetcursor();
 if(++ttvx==40)
 {
  if(ttvy)
  {
   ttvx=0;
   mxdown();
  }
  else
   ttvx--;
 }
}



void mxleft(void)
{
 vxsetcursor();
 if(--ttvx==-1)
 {
  if(ttvy)
  {
   ttvx=39;
   mxup();
  }
  else
   ttvx++;
 }
}


/*****************************************************************************/


int mxclrlatent(int byte)
{
 if(byte==SPC && mxlatent)  /* field delimiter */
 {
  byte=MXSPC+32;
  mxvalidate();
 }
 else
 if((byte==(MXGRSPC+32) || byte>=(MXGSTART+32)) && mxlatent) /* graphics */
 {
  if(byte==(MXGRSPC+32)) mxvalidate();
  else                   mxvalidategr();
 }

 return(byte);
}



void mxwritechar(int byte,int style,int x,int y)
{
 vscr->lmod[y]=1;

 if((vscr->tcbuf[y][x] & MXDH) && y<24) vscr->lmod[y+1]=1;

 if(byte==MXSPC)
 {
  if(mxrealcnc) style|=MXCNC;

  if(mxrealul)  style|=MXUNDER;

  vscr->tcbuf[y][x]=style+byte;
  if((style & MXDH) && y<24) vscr->lmod[y+1]=1;
 }
 else
 {
  vscr->tcbuf[y][x]=style+byte;
  if((style & MXDH) && y<24) vscr->lmod[y+1]=1;
 }
}



void mxwritecharmid(int byte,int x,int y)
{
 int fill;

 if(byte==MXSPC) fill=MXSPC;
 else            fill=0;

 if(y>1 && (vscr->tcbuf[y-1][x] & MXDH))
 {
  vscr->tcbuf[y-1][x]^=MXDH;
  vscr->lmod[y-1]=1;
 }

 if((mxstyle & MXDH) && (y>1))
 {
  mxwritechar(byte,mxstyle,x,y-1);
  mxwritechar(fill,mxstyle ^ MXDH,x,y);
  if((mxstyle & MXDW) && x<39)
  {
   mxwritechar(fill,mxstyle ^ MXDW,x+1,y-1);
   mxwritechar(fill,mxstyle ^ (MXDH|MXDW),x+1,y);
  }
 }
 else    /* just double width */
 {
  mxwritechar(byte,mxstyle,x,y);
  if((mxstyle & MXDW) && x<39) mxwritechar(fill,mxstyle ^ MXDW,x+1,y);
 }
}



/* erase to EOL */

void mxeol(void)
{
 int i;
 int byte;

 if(mxset==1) 
 {
  if(mxlatent) mxvalidategr();
  byte=MXGRSPC+32;
 }
 else
 {
  byte=32;
 }

 if(mxstyle & MXDW)
  for(i=ttvx;i<40;i+=2) mxwritecharmid(byte-32,i,ttvy);
 else
  for(i=ttvx;i<40;i++)  mxwritecharmid(byte-32,i,ttvy);
 mxmodded=1;
}



void mxwritecharhi(int byte)
{
 mxlast=byte;

 byte=mxclrlatent(byte);

 mxmodded=1;
 vxsetcursor();

 if((mxstyle & (MXDW|MXDH))==(MXDW|MXDH))
 {
  if(ttvx<39 && ttvy>1)
  {
   mxwritecharmid(byte-32,ttvx,ttvy);

   if(ttvx==38)
   {
    if(mxscroll && ttvy>=23)
    {
     ttvy=vscr->height-1;
     if(ttvy==24) mxscrollscreen(2,vscr);
     else         mxscrollscreen(1,vscr);
    }
    else
    if((ttvy==23 || ttvy==24) && !mxscroll) ttvy=2;
    else                                    ttvy+=2;

    ttvx=0;
   }
   else
   {
    mxright();
    mxright();
   }
  }
  else
  if(ttvx==39 && ttvy>1)
  {
   mxwritecharmid(byte-32,ttvx,ttvy);
   if(mxscroll && ttvy>=23)
   {
    ttvy=vscr->height-1;
    if(ttvy==24) mxscrollscreen(2,vscr);
    else         mxscrollscreen(1,vscr);
   }
   else
   if((ttvy==23 || ttvy==24) && !mxscroll) ttvy=2;
   else                                    ttvy+=2;

   ttvx=0;
  }
 }
 else
 if(mxstyle & MXDW)
 {
  if(ttvx<39)
  {
   mxwritecharmid(byte-32,ttvx,ttvy);
   mxright();
   mxright();
  }
  else
  {
   mxwritecharmid(byte-32,ttvx,ttvy);
   mxright();
  }
 }
 else
 if(mxstyle & MXDH)
 {
  if(ttvy>1)
  {
   mxwritecharmid(byte-32,ttvx,ttvy);
   if(ttvx==39)
   {
    if(mxscroll && ttvy>=23)
    {
     ttvy=vscr->height-1;
     if(ttvy==24) mxscrollscreen(2,vscr);
     else         mxscrollscreen(1,vscr);
    }
    else
    if((ttvy==23 || ttvy==24) && !mxscroll) ttvy=2;
    else                                    ttvy+=2;

    ttvx=0;
   }
   else mxright();
  }
 }
 else
 {
  mxwritecharmid(byte-32,ttvx,ttvy);
  mxright();
 }

 if(!spconcode && spoolflag)
 {
  myspool(mxisomap[byte]);
 }
}


/*****************************************************************************/
/* main terminal input for Minitel */


void minitelx(int byte)
{
 int i;


 if(byte==NUL) return;
 else
 if(mxsink1)
 {
  mxsink1=0;
  return;
 }

 if(vxhash)
 {
  vxhash=0;
  if(byte=='7' && ttns) 
  {
   vtsetfocusfront();
   return;
  }
  else
  if(byte=='0')
  {
   setterm(TERMVX);
   return;
  }
  else
  if(byte=='9') byte=12;
 }

 if(viewescflag)
 {
  viewescflag=vxhash=0;

  if(ttns)
  {
   if(byte=='a') 
   {
    vtsetfocusfront();
    return;
   }
   else
   if(byte=='c') byte=12;
  }

  if(byte=='#')
  {
   vxhash=1;
   return;
  }

  if(byte!=12)
  {
   if(byte<128) byte+=64;

   if(byte>159 || byte<128)
   {
    if(byte==(':'+64)) mxesc=1;
    else
    if(byte==('#'+64)) mxesc=10;
    else
    if(byte==('%'+64)) mxtrans=1;
    else
    if(byte==('5'+64)) mxsink1=1;
    else
    if(byte==('6'+64)) mxsink1=1;
    else
    if(byte==('7'+64)) mxsink1=1;
    else
    if(byte==('9'+64)) mxsink1=1;
    {
     /*  mxright();      */
    /* dprintf(0,"byte=%x",byte-64); */
    }

    return;
   }
  }
 }


 if(byte<32)
 {
  switch(byte)
  {
   case ENQ:
            vxanswerback();
            break;

   case BEL:
            if(vxbeep) beep();
            break;

   case   8: /* APB ^H */
            mxleft();
            break;

   case   9: /* APF ^I */
            mxright();
            break;

   case  10: /* APD ^J */
            mxdown();
            break;

   case  11: /* APU ^K */
            mxup();
            break;

   case  12: /* CLS     ^L */
            mxcls();
            break;

   case CR: /* APR      ^ M */
           if(!spconcode && spoolflag)
           {
            myspool(CR);
            if(vxrxcrlnf) myspool(LF);
           }
           
           if(vxrxcrlnf)
           {
            mxcrlf();
           }
           else
           {
            vxsetcursor();
            ttvx=0;
           }
           break;


   case  14: /* SO  ^N */
            mxset=1;
            mxpendul=mxrealul=0;
            mxstyle&=~(MXUNDER|MXINV|MXDW|MXDH); /* polarity/size no effect */
            mxsetstylec();
            break;


   case  15: /* SI ^O */
            mxset=0;
            mxpendul=mxrealul=0;
            mxstyle&=~(MXUNDER|MXINV|MXDW|MXDH);
            mxsetstylec();
            break;


   case  17: /* CON ^Q */
            vxcurs=vxcursphase=1;
            vxsetcursor();
            break;


   case  18: /* RPT Repeat -- format RPT char     ^R                  */
             /* 6 least sig bits of char, times to repeat last graphic */
            mxrep=1; 
            break;

  case  19:  /* SEP */
            mxsink1=1;
            break;


   case  20: /* COF ^T */
            vxsetcursor();
            vxcurs=0;
            break;


   case  24: /* CAN ^X */
            mxeol();
            break;

   case  22:                        /* maybe SYN too */

   case  25: /* SS2  ^Y */
            if(mxset==0) mxss2=1;   /* Can't do SS2 in G1 */
            break;


   case  27:  /* ^[ */
            viewescflag=1;
            break;

   case  29: /* SS3 */
            mxsink1=1;
            break;

   case  30: /* APH Home ^^ */
            vxsetcursor();
            ttvx=0;
            ttvy=vscr->start;
            mxdefltcols();
            break;

   case  31: /* APA tabs to a position followed by x, y chars ^_ */
            mxapa=1;
            break;

  }
  return;
 }
 else
 if(byte>=128)
 {
  switch(byte)
  {
   case 128:     /* BKF to WHF */
   case 129:     /* @-G */
   case 130:
   case 131:
   case 132:
   case 133:
   case 134:
   case 135:
            mxforeground=byte-128;
            mxsetstylec();
            break;

   case 136:    /* FSH Flash  H */
            mxstyle|=MXFLASH1;
            break;

   case 137:    /* STD Steady I */
            mxstyle&=~(MXFLASH1+MXFLASH2);
            break;

   case 138:    /* EBX End box J */
                /* Not Used */
            break;

   case 139:    /* SBX Start box K */
                /* Not Used */
            break;

   case 140:    /* NSZ Normal size L */
            mxstyle&=~(MXDH|MXDW);
            break;

   case 141:    /* Double Height M */
            if(mxset!=1 && ttvy>1)
            {
             mxstyle&=~(MXDH|MXDW);
             mxstyle|=MXDH;
            }
            break;

   case 142:    /* Double Width N */
            if(mxset!=1)
            {
             mxstyle&=~(MXDH|MXDW);
             mxstyle|=MXDW;
            }
            break;

   case 143:    /* Double Size O */
            if(mxset!=1 && ttvy>1) mxstyle|=(MXDH|MXDW);
            break;

   case 144:    /* BKB to WHB */
   case 145:    /* P-W */
   case 146:
   case 147:
   case 148:
   case 149:
   case 150:
   case 151:
            mxbackgroundl=byte-144;
            mxlatent=1;
            break;

   case 152:   /* CDY Conceal X */
            mxpendcnc=1;
            mxlatent=1;
            break;

   case 153:   /* SPL Underline off Y */
            if(mxset==1) mxstyle&=~MXUNDER;
            else
            {
             mxpendul=0;
             mxlatent=1;
            }
            break;

   case 154:   /* STL Underline on  Z */
            if(mxset==1) mxstyle|=MXUNDER;
            else
            {
             mxpendul=1;
             mxlatent=1;
            }
            break;

   case 155:   /* CSI [ */
               /* Not Used */

           /* dprintf(0,"CSI"); */
           /* mxesc=20; */
            break;

   case 156:   /* NPO Normal polarity \  */
            if(mxset!=1)
            {
             mxstyle&=~MXINV;
             mxsetstylec();
            }
            break;

   case 157:   /* IPO Inverse polarity ] */
            if(mxset!=1)
            {
             mxstyle|=MXINV;
             mxsetstylec();
            }
            break;

   case 158:   /* TRB Transparent Background */
               /* Not Used */
            break;

   case 159:   /* SCD Reveal */
            mxpendcnc=0;
            mxlatent=1;
            break;

  }
  return;
 }
 else
 if(mxesc)
 {
  if(mxesc==1) 
  {
   mxesc1=byte;
   mxesc=2;
  }
  else
  if(mxesc==2)
  {
   mxesc=0;
   if(byte=='C')
   {
    if(mxesc1=='i') mxscroll=1;
    else
    if(mxesc1=='j') mxscroll=0;
   }
  }
  else
  if(mxesc==10)
  {
   if(byte==' ') mxesc=11;
   else          mxesc=0;
  }
  else
  if(mxesc==11)
  {
   if(byte=='X') mxconceal();
   else
   if(byte=='_') mxreveal();
   mxesc=0;
  }
 }
 else
 if(mxapa)         /* tabbing around */
 {
  if(mxapa==1)
  {
   mxapax=byte-65;  /* was 65 +1 */
   mxapa++;
  }
  else
  {
   i=byte-65;

   if((i>=0 && i<40) && (mxapax>=-1 && mxapax<24))
   {
    vxsetcursor();
    ttvx=byte-65;
    ttvy=mxapax+1;
    if(!ttvy) mxenterstatusline();
    mxdefltcols();
   }
   else
   if((mxapax+65)>='0' && (mxapax+65)<='9' && byte>='0' && byte<='9')
   {
    i=(mxapax+65-'0')*10+byte-'0';

    if(i>=0 && i<=24)
    {
     vxsetcursor();
     ttvx=0;
     ttvy=i;
     if(!ttvy) mxenterstatusline();
     mxdefltcols();
    }
   }
   mxapa=0;
  }
 }
 else
 if(mxrep)         /* repeat */
 {
  mxrep=0;
  byte=(byte & 0x3F);
  for(i=0;i<byte;i++) mxwritecharhi(mxlast);
 }
 else
 if(mxss2)
 {
  if(mxss2==1)
  {
   if(byte>=64 && byte<80)      /* it's an accent */
   {
    mxss2=2;
    mxss2first=byte;
   }
   else
   {
    mxwritecharhi(mxgmap(byte,2));
    mxss2=0;
   }
  }
  else
  {                              /* at this point we trap accented chars */
   mxss2=0;
   mxwritecharhi(mxg2cc(byte,mxss2first));
  }
 }
 else mxwritecharhi(mxgmap(byte,mxset));
}

