/***************************************************************************
 *                                                                         *
 *   MDLOGIC.C                                                             *
 *                                                                         *
 *   Copyright (c) 1992-1997 Galacticomm, Inc.    All rights reserved.     *
 *                                                                         *
 *   This is the callable ANSI screen builder utility for                  *
 *   use with Worldgroup.                                                  *
 *                                                                         *
 *                       - S. Brinker & T. Stryker    01/21/92             *
 *                                                                         *
 ***************************************************************************/

#include "gcomm.h"
#if defined( GCWINNT )
#  include "windows.h"
#endif
#include "majorbbs.h"
#include "mdlogic.h"

#define FILREV "$Revision: 11 $"

#define CURUP  0,-1                /* movcur parms: move cursor up         */
#define CURDN  0,+1                /* movcur parms: move cursor down       */
#define CURLF  -1,0                /* movcur parms: move cursor left       */
#define CURRT  +1,0                /* movcur parms: move cursor right      */

#define INTATR      0x1E           /* introduction box attribute           */
#define REGATR      0x07           /* "regular" (default) attribute        */
#define QRFATR      0x0B           /* quick reference line attribute       */
#define QRKATR      0x0E           /* quick reference key attribute        */
#define INVATR      0x70           /* "inverse" attribute                  */
#define CBXATR      0x04           /* color box attribute                  */
#define CBBATR      0x30           /* highlighted "box" attribute          */
#define KBXATR      0x4E           /* key/marker ruler attribute           */
#define KBBATR      0xCE           /* key/marker blinking char attribute   */

#define NFCOLS      16             /* number of foreground colors          */
#define NBCOLS      8              /* number of background colors          */

#define ULX    0                   /* upper left window x position         */
#define ULY    0                   /* upper left window y position         */
#define LRX    79                  /* lower right window x position        */
#define LRY    24                  /* lower right window y position        */

#define DFTATR      0x0A           /* default attribute when starting MD   */

CHAR *scnbuf;                      /* static buffer of our screen          */
CHAR *tmpbuf;                      /* temporary screen buffer              */
CHAR filnam[100];                  /* static buffer of our file name       */
static INT x,y;                    /* current (x,y) position               */
static INT attr=DFTATR;            /* current atrribute                    */
INT scropt;                        /* current "scroll option" for window   */
static INT fksinu;                 /* function key drawing tools in use    */
static INT qrftog;                 /* toggle: display quick reference?     */
static INT blinkm;                 /* toggle: display key markers?         */
static INT ylim;                   /* y-axis limit (quick ref or not?)     */
static INT kfromh;                 /* alt- keystroke from help screen      */
INT mddone;                        /* are we done yet?                     */
INT changed;                       /* something changed in this file?      */
static INT fore,back;              /* foreground and background indexes    */
INT finalx,finaly;                 /* final (x,y) cursor position          */
INT finalc;                        /* final cursor color                   */
INT savwcs;                        /* save with clear screen?              */
static INT insmod;                 /* 0=regular mode; 1=insert mode        */
INT lastx,lasty;                   /* bottom of active screen              */
static INT psbend=0;               /* possible end-of-line ANSI moves      */

#define MXRDLN      6              /* max. # of "restorable" deleted lines */
CHAR dlines[MXRDLN][80*2];         /* buffer of deleted lines              */
static INT dlbidx;                 /* deleted line buffer index            */

struct marker *markers=NULL;       /* static array of markers              */
INT nmarks;                        /* current total of markers             */

struct txtvar *tvars;              /* static array of text variables       */
static INT nvars;                  /* current total of text variables      */

INT tabtbl[10]={                   /* array of tab positions               */
     0,8,16,24,32,40,48,56,64,72
};
INT fkxtbl[10][10]={               /* array of soft key drawing characters */
   {201,187,200,188,205,186,202,203,204,185},/* double bar box chars       */
   {218,191,192,217,196,179,193,194,195,180},/* single bar box chars       */
   {214,183,211,189,208,210,199,182,215,206},/* double/single box chars    */
   {213,184,212,190,207,209,198,181,216,197},/* single/double box chars    */
   {176,177,178,219,220,221,222,223,254, 22},/* solid box-type chars       */
   { 28,  2,  3,  4,  5,  6,236,239,  9,251},/* misc low-value chars       */
   { 11, 21, 22, 14, 15, 20, 21, 23,171,172},/* misc chars & fraction chars*/
   { 16, 17, 18, 24, 25,240,250, 29, 30, 31},/* arrows and such chars      */
   {160,130,161,162,164,132,148,129,168,173},/* common foreign chars       */
   {224,225,228,246,251,253,241,237,244,245} /* misc high-value chars      */
};

CHAR *atbrul={
"ÚÂÂÂÅÂÂÂÂ1ÂÂÂÂÅÂÂÂÂ2ÂÂÂÂÅÂÂÂÂ3ÂÂÂÂÅÂÂÂÂ4ÂÂÂÂÅÂÂÂÂ5ÂÂÂÂÅÂÂÂÂ6ÂÂÂÂÅÂÂÂÂ7ÂÂÂÂÅÂÂÂÂ8"};
CHAR *btbrul={
"ÀÁÁÁÅÁÁÁÁ1ÁÁÁÁÅÁÁÁÁ2ÁÁÁÁÅÁÁÁÁ3ÁÁÁÁÅÁÁÁÁ4ÁÁÁÁÅÁÁÁÁ5ÁÁÁÁÅÁÁÁÁ6ÁÁÁÁÅÁÁÁÁ7ÁÁÁÁÅÁÁÁÁ8"};

CHAR *justbl[]={                   /* array of justification names         */
     "None",
     "Left",
     "Right",
     "Center",
     NULL
};
CHAR justlt[]={"NLRC"};            /* table of justification 1st-letters   */

CHAR *tryext[3][3]={               /* table of file extensions to try      */
     {"ibm","ans","asc"},
     {"ans","asc","ibm"},
     {"asc","ans","ibm"}
};
#define IBMFIL      0              /*   try .ibm file first                */
#define ANSFIL      1              /*   try .ans file first                */
#define ASCFIL      2              /*   try .asc file first                */

static
INT astf[]={0,4,2,6,1,5,3,7};      /* ansi/attribute xlate tbl (both ways!)*/

#if defined( GCWINNT )
static const CHAR *helpFn="";      /* Win32 help file name                 */
static GBOOL usingWinHelp=FALSE;   /* set to true if WinHelp called        */
static ULONG helpId=131331;        /* WGSDRAW help ID in wgscnf.hlp        */
#endif

CHAR *blobuf;                      /* temp buffer for block operations     */
INT bulx,buly,blrx,blry;           /* block location variables             */
INT lx,ly;                         /* mdload temporary x,y coords          */
CHAR *ldsp;                        /* mdload temporary screen pointer      */
INT cldatr;                        /* mdload temporary screen attribute    */

VOID delkm(struct marker *mptr);
VOID shfllf(VOID);
VOID setbdr(INT color);
VOID dsptvs();
#if defined( GCWINNT )
static HWND GetMainWindow(VOID);   /* get console's main window handle     */
static GBOOL exists(const char *fname);  /* check for existence of a file  */
#endif

VOID
inimdl(VOID)
{
     scropt=kfromh=fksinu=mddone=changed=blinkm=insmod=0;
     qrftog=1;
     ylim=24;
     dlbidx=-1;
     clrfxyc();
     if (scnbuf == NULL) {
          scnbuf=alcmem(GVIDSCNSIZ);
          tmpbuf=alcmem(GVIDSCNSIZ);
          blobuf=alcmem(GVIDSCNSIZ);
          tvars=(struct txtvar *)alcmem(sizeof(struct txtvar)*MXTXTV);
     }
     nvars=0;
}

VOID
mdesc(VOID)
{
     if (!changed || blowoff()) {
          mddone=1;
     }
}

INT
xmdnow(VOID)
{
     if (!changed) {
          mddone=1;
     }
     return(mddone);
}

VOID
mdmain(                            /* main input handler                   */
GBOOL accmrk,                      /*   allow use of block marks?          */
VOID (*xitrou)(INT c))             /*   function to call when done         */
{
     INT i,c;
#if defined( GCWINNT )
     HWND hwnd;                    /* main window's handle                 */
#endif

     cursiz(GVIDLILCURS);
     setbdr(7);
     setwin(0L,ULX,ULY,LRX,LRY,scropt);
     rfrscn();
     x=y=0;
     while (!mddone) {
          if (y == lasty && (x-1) > lastx) {
               x=lastx;
               updqrf();
          }
          setatr(attr);
          locate(x,y);
          if (kfromh) {
               c=kfromh;
               kfromh=0;
          }
          else {
               c=getchq();
          }
          switch (c) {
          case CRSRLF:
               movcur(CURLF);
               break;
          case CRSRRT:
               movcur(CURRT);
               break;
          case CRSRUP:
               movcur(CURUP);
               break;
          case CRSRDN:
               movcur(CURDN);
               break;
          case HOME:
               x=0;
               updqrf();
               break;
          case CTRLHOME:
               x=y=0;
               updqrf();
               break;
          case END:
               jmp2eol();
               updqrf();
               break;
          case CTRLEND:
               x=lastx;
               y=lasty;
               updqrf();
               break;
          case PGUP:
          case PGDN:
               (*xitrou)(c);
               break;
          case TAB:
               for (i=0 ; i < nelems(tabtbl) ; i++) {
                    if (x < tabtbl[i]) {
                         x=tabtbl[i];
                         break;
                    }
               }
               if (i == nelems(tabtbl)) {
                    x=LRX;
               }
               updqrf();
               break;
          case BAKTAB:
               for (i=nelems(tabtbl) ; i >= 0 ; i--) {
                    if (x > tabtbl[i]) {
                         x=tabtbl[i];
                         break;
                    }
               }
               updqrf();
               break;
          case INS:
               cursiz(insmod ? GVIDLILCURS : GVIDBIGCURS);
               insmod=(insmod ? 0 : 1);
               break;
          default:
               if (blinkm) {
                    blinkm=0;
                    rfrscn();
                    if ((c>>8) == 0) {
                         break;
                    }
               }
               switch (c) {
               case '\r':
                    x=0;
                    if ((y=min(ylim-1,y+1)) > lasty) {
                         lasty++;
                         lastx=-1;
                         rfrlin();
                    }
                    else {
                         updqrf();
                    }
                    break;
               case '\b':
#ifdef GCDOS
                    if (lascan() != 0) {
#endif // GCDOS
                         if (tvinxy(max(x-1,0),y) != NULL) {
                              break;
                         }
                         if (x != 0) {
                              x--;
                              shfllf();
                         }
                         else if (y == lasty && y != 0) {
                              delkm(kminxy(x,y));
                              scnbuf[gvscnoff(0,y)]=' ';
                              scnbuf[gvscnoff(0,y)+1]=0x07;
                              lasty--;
                              y=lasty;
                              x=lastx=LRX;
                         }
                         rfrlin();
#ifdef GCDOS
                    }
                    else {
                         putit(c);
                    }
#endif // GCDOS
                    break;
               case DEL:
                    if (x == finalx && y == finaly) {
                         finalx=finaly=-1;
                         rfrlin();
                    }
                    else if (y == lasty && x >= lastx) {
                         if (x == 0) {
                              if (lastx == 0) {
                                   lastx--;
                                   scnbuf[gvscnoff(x,y)]=' ';
                                   scnbuf[gvscnoff(x,y)+1]=0x07;
                                   rfrlin();
                              }
                         }
                         else {
                              x--;
                              lastx--;
                              scnbuf[gvscnoff(x+1,y)]=' ';
                              scnbuf[gvscnoff(x+1,y)+1]=0x07;
                              rfrlin();
                         }

                    }
                    else if (x != LRX && tvinxy(x,y) == NULL) {
                         shfllf();
                         rfrlin();
                    }
                    break;
               case ALT_A:
                    colbox();
                    break;
               case ALT_B:
                    block();
                    break;
               case ALT_C:
                    divlin();
                    break;
               case ALT_E:
                    cvt2asc();
                    break;
               case ALT_F:
                    setfxyc();
                    break;
               case ALT_H:
#if defined (GCWINNT)              /* under NT/95, try to use WinHelp      */
                    if (exists(helpFn)) {
                         hwnd=GetMainWindow();
                    }
                    else {
                         hwnd=NULL;  /* don't even try if no help file     */
                    }

                    if (hwnd != NULL) {
                         WinHelp(hwnd,helpFn,HELP_CONTEXT,helpId);
                         usingWinHelp=TRUE;
                    }
                    else
                    {
#endif
                         scn2mem(tmpbuf,0,GVIDSCNSIZ);
                         explode(scntbl[HLPSCN],1,1,75,23);
                         hidecursor();
                         if ((c=getchc()) > 255 && c != ALT_H) {
                              kfromh=c;
                         }
                         rfrscn();
#if defined( GCWINNT )
                    }
#endif
                    break;
               case ALT_I:
                    inslin();
                    break;
               case ALT_J:
                    joilin();
                    break;
               case ALT_K:
                    if (accmrk) {
                         if (!blinkm) {
                              blinkm=1;
                              shwkmk();
                         }
                         else {
                              blinkm=0;
                              rfrscn();
                         }
                    }
                    break;
               case ALT_L:
                    getload();
                    break;
               case ALT_M:
                    if (accmrk) {
                         keymrk();
                    }
                    break;
               case ALT_N:
                    clrall();
                    break;
#ifdef GCDOS
               case ALT_O:
                    onlsim();
                    break;
#endif
               case 114*256:  /* Ctrl-PrtScn */
               case ALT_Q:
                    if (qrftog) {
                         qrftog=0;
                         hidqrf();
                    }
                    else {
                         qrftog=1;
                         shwqrf();
                    }
                    break;
               case ALT_R:
                    rstlin();
                    break;
               case ALT_U:
                    attr=scnbuf[gvscnoff(x,y)+1];
                    updqrf();
                    break;
               case ALT_V:
                    addtxv();
                    break;
               case ALT_W:
                    withcs();
                    break;
               case ESC:
#ifdef GCDOS
                    if (lascan() == 0) {
                         putit(c);
                         break;
                    }
#endif // GCDOS
               case ALT_S:
               case ALT_X:
                    (*xitrou)(c);
                    break;
               case ALT_Y:
                    rmvlin();
                    break;
               case ALT_Z:
                    zaptxv();
                    break;
               case F1:
               case F2:
               case F3:
               case F4:
               case F5:
               case F6:
               case F7:
               case F8:
               case F9:
               case F10:
                    putit(fkxtbl[fksinu][(c-F1)>>8]);
                    break;
               case ALT+F1:
               case ALT+F2:
               case ALT+F3:
               case ALT+F4:
               case ALT+F5:
               case ALT+F6:
               case ALT+F7:
               case ALT+F8:
               case ALT+F9:
               case ALT+F10:
                    fksinu=(c>>8)-104;
                    if (qrftog) {
                         shwqrf();
                    }
                    break;
               default:
                    if (1 <= c && c <= 255) {
                         putit(c);
                    }
               }
               if (c != ALT_S) {
                    changed=1;
               }
          }
     }
     setatr(0x07);
     rstwin();
     setbdr(0);
}

VOID
shwqrf(VOID)
{
     INT i;

     ylim=24;
     if (y == ylim) {
          y=ylim-1;
     }
     locate(0,24);
     setatr(QRFATR);
     printf(" Alt-H for help ³ Pos: (%02d,%02d) ³",x+1,y+1);
     setatr(attr);
     printf(" Color ");
     setatr(QRFATR);
     printf("³ ");
     for (i=0 ; i < 9 ; i++) {
          setatr(QRFATR);
          printf("%d=",i+1);
          setatr(QRKATR);
          printf("%c ",fkxtbl[fksinu][i]);
     }
     setatr(QRFATR);
     printf("0=");
     setatr(QRKATR);
     printf("%c",fkxtbl[fksinu][i]);
     qrftog=1;
}

VOID
keymrk(VOID)
{
     INT rulery,c,done=0,i,newval=0;
     CHAR chpatr;
     struct marker *mptr,mbakup;
     struct txtvar *vptr;

     if ((mptr=kminxy(x,y)) == NULL) {
          if (nmarks+1 >= MXMARK) {
               printf("\7");
               return;
          }
          scn2mem(tmpbuf,0,GVIDSCNSIZ);
          explode(scntbl[MSCSCN],10,5,63,7);
          if (!isselc(c=getchc())) {
               rfrscn();
               return;
          }
          mptr=&markers[nmarks++];
          mptr->line=y;
          if ((vptr=tvinxy(x,y)) != NULL) {
               mptr->startx=vptr->startx;
               mptr->endx=vptr->endx;
          }
          else {
               mptr->startx=mptr->endx=x;
          }
          mptr->select=toupper(c);
          mem2scn(tmpbuf,0,GVIDSCNSIZ);
          newval=1;
     }
     movmem(mptr,&mbakup,sizeof(struct marker));
     scn2mem(tmpbuf,0,GVIDSCNSIZ);
     setatr(KBXATR);
     if (y < 5) {
          explode(scntbl[MSCSCN],5,8,68,10);
          locate(0,y+1);
          printf(btbrul);
          locate(0,y+2);
          printf("%80s","");
          rulery=y+2;
     }
     else {
          explode(scntbl[MSCSCN],5,1,68,3);
          locate(0,y-1);
          printf(btbrul);
          locate(0,y-2);
          printf("%80s","");
          rulery=y-2;
     }
     while (!done) {
          mem2scn(&scnbuf[gvscnoff(0,y)],gvscnoff(0,y),80*2);
          for (i=mptr->startx ; i <= mptr->endx ; i++) {
               chpatr=scngetc(gvscnoff(i,y)+1);
               chpatr^=0x77;
               scnputc(gvscnoff(i,y)+1,chpatr);
          }
          setatr(KBXATR);
          locate(mptr->startx,rulery);
          printf("%c",mptr->select);
          setatr(KBBATR);
          locate(mptr->endx,rulery);
          printf("%c",mptr->select);
          hidecursor();
          switch (getchc()) {
          case '\b':
          case CRSRLF:
               if (mptr->endx != mptr->startx) {
                    locate(mptr->endx,rulery);
                    printf(" ");
                    if ((vptr=tvinxy(mptr->endx,y)) != NULL) {
                         if (vptr->startx == 0 || mptr->startx == vptr->startx) {
                              break;
                         }
                         mptr->endx=vptr->startx-1;
                    }
                    else {
                         mptr->endx--;
                    }
               }
               break;
          case CRSRRT:
               if (mptr->endx != (mptr->line == lasty ? lastx : LRX)
                  && kminxy(mptr->endx+1,y) == NULL) {
                    locate(mptr->endx,rulery);
                    printf(" ");
                    if ((vptr=tvinxy(mptr->endx+1,y)) != NULL) {
                         mptr->endx=vptr->endx;
                    }
                    else {
                         mptr->endx++;
                    }
               }
               break;
          case END:
               locate(mptr->endx,rulery);
               printf(" ");
               for ( ; mptr->endx < LRX && kminxy(mptr->endx+1,y) == NULL ; ) {
                    if ((vptr=tvinxy(mptr->endx+1,y)) != NULL) {
                         mptr->endx=vptr->endx;
                    }
                    else {
                         mptr->endx++;
                    }
               }
               break;
          case HOME:
               locate(mptr->endx,rulery);
               printf(" ");
               mptr->endx=mptr->startx;
               break;
          case TAB:
               locate(mptr->endx,rulery);
               printf(" ");
               for (i=0 ; i < nelems(tabtbl) ; i++) {
                    if (mptr->endx < tabtbl[i]) {
                         while (mptr->endx < tabtbl[i]) {
                              if (kminxy(mptr->endx+1,y) != NULL) {
                                   break;
                              }
                              mptr->endx++;
                         }
                         break;
                    }
               }
               if (i == nelems(tabtbl)) {
                    mptr->endx=LRX;
               }
               if (mptr->line == lasty && mptr->endx > lastx) {
                    mptr->endx=lastx;
               }
               break;
          case BAKTAB:
               locate(mptr->endx,rulery);
               printf(" ");
               for (i=nelems(tabtbl) ; i >= 0 ; i--) {
                    if (mptr->endx > tabtbl[i]) {
                         while (mptr->endx > tabtbl[i]) {
                              if (mptr->endx == mptr->startx) {
                                   break;
                              }
                              mptr->endx--;
                         }
                         break;
                    }
               }
               break;
          case DEL:
               if (&markers[--nmarks] != mptr) {
                    movmem(mptr+1,mptr,
                           (nmarks-(INT)(mptr-markers))*sizeof(struct marker));
               }
               done=1;
               break;
          case ESC:
               if (!newval) {
                    movmem(&mbakup,mptr,sizeof(struct marker));
               }
               else {
                    nmarks--;
               }
          case 13:
               done=1;
               break;
          default:
               if (isselc(c)) {
                    mptr->select=toupper(c);
               }
          }
          if ((vptr=tvinxy(mptr->endx,y)) != NULL) {
               mptr->endx=vptr->endx;
          }
     }
     rfrscn();
}

VOID
addtxv(VOID)
{
#define TXVSTT      0              /* entering text variable name state    */
#define JSTSTT      1              /* selecting justification state        */
#define LENSTT      2              /* entering format length state         */
#define SVTSTT      3              /* choosing to save or not state        */
     static CHAR jststg[7]="None";
     static CHAR lenstg[3]="";
     static CHAR yesans[4];
     struct txtvar *vptr,vbakup;
     struct marker *mptr;
     INT done=0,state=TXVSTT,i,oldendx,newval=0;

     strcpy(yesans,"Yes");
     if ((vptr=tvinxy(x,y)) == NULL) {
          if (nvars+1 == MXTXTV) {
               return;
          }
          if (kminxy(x,y) != NULL) {
               explode(scntbl[ERRSCN],11,2,67,7);
               hidecursor();
               getchc();
               rfrscn();
               return;
          }
          vptr=&tvars[nvars++];
          setmem(vptr,sizeof(struct txtvar),0);
          vptr->line=y;
          vptr->startx=x;
          newval=1;
     }
     movmem(vptr,&vbakup,sizeof(struct txtvar));
     oldendx=vptr->endx;
     explode(scntbl[TXVSCN],16,3,55,16);
     setatr(0x1E);
     locate(34,8);
     printf(vptr->name);
     locate(34,9);
     strcpy(jststg,justbl[(SHORT)vptr->just]);
     printf(jststg);
     if (jststg[0] != 'N') {
          locate(34,10);
          strcpy(lenstg,spr("%d",vptr->length));
          printf(lenstg);
     }
     while (!done) {
          switch (state) {
          case TXVSTT:
               while (1) {
                    if (!edtval(34,8,TVRSIZ,vptr->name,istxvc,ALLCAPS+MULTIEX)) {
                         done=-1;
                         break;
                    }
                    if (vptr->name[0] != '\0') {
                         break;
                    }
                    printf("\7");
               }
               state=(edtvalc == CRSRUP || edtvalc == CRSRLF ? TXVSTT : JSTSTT);
               break;
          case JSTSTT:
               if (!edtchc(34,9,jststg,justbl,MULTIEX)) {
                    done=-1;
               }
               if (jststg[0] == 'N') {
                    lenstg[0]='\0';
                    state=(edtvalc == CRSRUP || edtvalc == CRSRLF ? TXVSTT : SVTSTT);
               }
               else {
                    state=(edtvalc == CRSRUP || edtvalc == CRSRLF ? TXVSTT : LENSTT);
               }
               break;
          case LENSTT:
               if (!edtval(34,10,sizeof(lenstg),lenstg,validig,MULTIEX)) {
                    done=-1;
               }
               if (atoi(lenstg) > 0 && atoi(lenstg) < (81-vptr->startx)) {
                    state=(edtvalc == CRSRUP || edtvalc == CRSRLF
                           ? JSTSTT : SVTSTT);
               }
               else {
                    printf("\7");
               }
               break;
          case SVTSTT:
               if (!edtval(40,12,sizeof(yesans),yesans,validyn,
                  MCHOICE+MULTIEX)) {
                    done=-1;
               }
               if (edtvalc == CRSRUP || edtvalc == CRSRLF) {
                    state=(jststg[0] == 'N' ? JSTSTT : LENSTT);
               }
               else {
                    vptr->attr=attr;
                    vptr->just=(INT)((CHAR *)strchr(justlt,jststg[0])-justlt);
                    vptr->length=(vptr->just == 0 ? strlen(vptr->name) :
                      atoi(lenstg));
                    vptr->endx=vptr->startx+vptr->length-1;
                    if (vptr->endx > LRX) {
                         vptr->length-=(vptr->endx-LRX);
                         vptr->endx=LRX;
                    }
                    if (vptr->line == lasty && vptr->endx > lastx) {
                         lastx=vptr->endx;
                    }
                    done=1;
               }
               break;
          }
     }
     if (done == -1) {
          if (!newval) {
               movmem(&vbakup,vptr,sizeof(struct txtvar));
          }
          else {
               nvars--;
          }
     }
     else {
          for (i=vptr->startx ; i <= vptr->endx ; i++) {
               if ((mptr=kminxy(i,y)) != NULL) {
                    if (mptr->startx <= vptr->startx
                      && mptr->endx >= vptr->endx) {
                         continue;
                    }
                    explode(scntbl[ERRSCN],11,2,67,7);
                    hidecursor();
                    getchc();
                    if (!newval) {
                         movmem(&vbakup,vptr,sizeof(struct txtvar));
                    }
                    else {
                         nvars--;
                    }
                    rfrscn();
                    return;
               }
          }
          ptvons(vptr);
          for (i=vptr->endx+1 ; i <= oldendx ; i++) {
               scnbuf[gvscnoff(i,vptr->line)]=' ';
               scnbuf[gvscnoff(i,vptr->line)+1]=attr;
          }
     }
     rfrscn();
}

VOID
dsptvs(VOID)                       /* re-display all text vars on the scn  */
{
     INT i;
     struct txtvar *vptr;

     for (i=0,vptr=tvars ; i < nvars ; i++,vptr++) {
          if (vptr->line <= ylim) {
               ptvons(vptr);
          }
     }
}

VOID
ptvons(vptr)
struct txtvar *vptr;
{
     INT i;
     static CHAR txvhold[81];
     CHAR *stgptr;

     strcpy(txvhold,spr("%c%c%c",TVARCH,justbl[(SHORT)vptr->just][0],
          vptr->length));
     strcat(txvhold,vptr->name);
     strcat(txvhold,spr("%c",TVARCH));
     fmttxv(txvhold,0);
     for (stgptr=txvhold ; *stgptr != '\0' ; stgptr++) {
          if (*stgptr == ' ') {
               *stgptr='*';
          }
     }
     for (i=vptr->startx,stgptr=txvhold ; i <= vptr->endx ; i++,stgptr++) {
          scnbuf[gvscnoff(i,vptr->line)]=*stgptr;
          scnbuf[gvscnoff(i,vptr->line)+1]=0x5E;
     }
}

VOID
zaptxv(VOID)
{
     INT i;
     struct txtvar *vptr;

     if ((vptr=tvinxy(x,y)) != NULL) {
          for (i=vptr->startx ; i <= vptr->endx ; i++) {
               scnbuf[gvscnoff(i,vptr->line)]=' ';
               scnbuf[gvscnoff(i,vptr->line)+1]=0x07;
          }
          if (&tvars[--nvars] != vptr) {
               movmem(vptr+1,vptr,
                (nvars-(INT)(vptr-tvars))*sizeof(struct txtvar));
          }
     }
     rfrscn();
}

struct marker *
kminxy(
INT kx,
INT ky)
{
     INT i;
     struct marker *mptr;

     for (i=0,mptr=markers ; i < nmarks ; i++,mptr++) {
          if (mptr->line == ky) {
               if (kx >= mptr->startx && kx <= mptr->endx) {
                    return(mptr);
               }
          }
     }
     return(NULL);
}

struct txtvar *
tvinxy(
INT vx,
INT vy)
{
     INT i;
     struct txtvar *vptr;

     for (i=0,vptr=tvars ; i < nvars ; i++,vptr++) {
          if (vptr->line == vy) {
               if (vx >= vptr->startx && vx <= vptr->endx) {
                    return(vptr);
               }
          }
     }
     return(NULL);
}

VOID
colbox(VOID)                       /* barf!  should use edtval()           */
{
     CHAR val[3];
     INT atoval;

     fore=attr&15;
     back=attr>>4;
     if (back > 7) {
          fore=fore+16;
          back=back-8;
     }
     explode(scntbl[COLSCN],10,1,66,16);
     locate(30,10);
     printf("  foreground=%-2d   ",fore);
     locate(30,11);
     printf("  background=%-2d   ",back);
     val[0]='\0';
     while (edtval(51,14,3,val,validig,0)) {
          if (val[0] == '\0') {
               break;
          }
          if ((atoval=atoi(val)) >= 0 && atoval < 32) {
               fore=atoval;
               break;
          }
          printf("\7");
     }
     val[0]='\0';
     while (edtval(51,15,2,val,validig,0)) {
          if (val[0] == '\0') {
               break;
          }
          if ((atoval=atoi(val)) >= 0 && atoval < 8) {
               back=atoval;
               break;
          }
          printf("\7");
     }
     if (fore > 15) {
          fore=fore-16;
          back=8+back;
     }
     attr=((back<<4)+fore);
     rfrscn();
}

VOID
block(VOID)
{
     INT bx,by,tx,ty,c,i,opt;
     INT culx,culy,clrx,clry;
     INT done=0;
     CHAR chpatr;
#define HLPBOXY 20
#define HLPBOXX 5
     INT hlpbox=1;

     hidecursor();
     bx=bulx=x;
     by=buly=y;
     chpatr=scngetc(gvscnoff(bx,by)+1);
     chpatr^=0x77;
     scnputc(gvscnoff(bx,by)+1,chpatr);
                                   /* some key like "b" for use last block */
     scn2mem(tmpbuf,0,GVIDSCNSIZ);
     if (buly <= HLPBOXY-2) {
          explode(scntbl[INTSCN],5,20,72,22);
     }
     else {
          explode(scntbl[INTSCN],5,1,72,3);
     }
     while (done == 0) {
          c=getchc();
          if (hlpbox) {
               mem2scn(tmpbuf,0,GVIDSCNSIZ);
               hlpbox=0;
          }
          switch (c) {
          case CRSRUP:
               if (by-1 >= buly) {
                    for (tx=bulx ; tx <= bx ; tx++) {
                         scnputc(gvscnoff(tx,by)+1,scnbuf[gvscnoff(tx,by)+1]);
                    }
                    by--;
               }
               break;
          case CRSRDN:
               if (by < min(lasty,ylim-1) && (by != lasty-1 || bx <= lastx)) {
                    by++;
                    for (tx=bulx ; tx <= bx ; tx++) {
                         chpatr=scngetc(gvscnoff(tx,by)+1);
                         chpatr^=0x77;
                         scnputc(gvscnoff(tx,by)+1,chpatr);
                    }
               }
               break;
          case CRSRLF:
               if (bx-1 >= bulx) {
                    for (ty=ULY ; ty <= by ; ty++) {
                         scnputc(gvscnoff(bx,ty)+1,scnbuf[gvscnoff(bx,ty)+1]);
                    }
                    bx--;
               }
               break;
          case CRSRRT:
               if ((by < lasty || bx < lastx) && bx < LRX) {
                    bx++;
                    for (ty=buly ; ty <= by ; ty++) {
                         chpatr=scngetc(gvscnoff(bx,ty)+1);
                         chpatr^=0x77;
                         scnputc(gvscnoff(bx,ty)+1,chpatr);
                    }
               }
               break;
          case TAB:
               tx=bx+1;
               for (i=0 ; i < nelems(tabtbl) ; i++) {
                    if (bx < tabtbl[i]) {
                         bx=tabtbl[i];
                         break;
                    }
               }
               if (i == nelems(tabtbl)) {
                    bx=LRX;
               }
               if (by == lasty && bx > lastx) {
                    bx=lastx;
               }
               for ( ; tx <= bx ; tx++) {
                    for (ty=buly ; ty <= by ; ty++) {
                         chpatr=scngetc(gvscnoff(tx,ty)+1);
                         chpatr^=0x77;
                         scnputc(gvscnoff(tx,ty)+1,chpatr);
                    }
               }
               break;
          case BAKTAB:
               tx=bx;
               for (i=nelems(tabtbl) ; i >= 0 ; i--) {
                    if (bx > tabtbl[i]) {
                         if (tabtbl[i] > bulx) {
                              bx=tabtbl[i];
                         }
                         break;
                    }
               }
               for (ty=buly ; ty <= by ; ty++) {
                    mem2scn(&scnbuf[gvscnoff(bx+1,ty)],gvscnoff(bx+1,ty),(tx-bx)*2);
               }
               break;
          case ' ':
          case 13:
               blrx=bx;
               blry=by;
               done=1;
               break;
          case ESC:
               done=-1;
               break;
          }
     }
     if (done == -1) {
          rfrscn();
          return;
     }
     blrx=bx;
     blry=by;
     movmem(scnbuf,blobuf,GVIDSCNSIZ);
     for (ty=buly ; ty <= blry ; ty++) {
          for (tx=bulx ; tx <= blrx ; tx++) {
               if (tvinxy(tx,ty) != NULL) {
                    scnputc(gvscnoff(tx,ty),blobuf[gvscnoff(tx,ty)]=' ');
                    scnputc(gvscnoff(tx,ty)+1,blobuf[gvscnoff(tx,ty)+1]=attr);
               }
          }
     }
     scn2mem(tmpbuf,0,GVIDSCNSIZ);
     explode(scntbl[INTSCN],6,17,71,19);
     done=0;
     switch (opt=toupper(getchc())) {
     case 'M':
          for (ty=buly ; ty <= blry ; ty++) {
               for (tx=bulx ; tx <= blrx ; tx++) {
                    if (tvinxy(tx,ty) == NULL) {
                         scnbuf[gvscnoff(tx,ty)]=' ';
                         scnbuf[gvscnoff(tx,ty)+1]=0x07;
                    }
               }
          }
     case 'C':
          mem2scn(tmpbuf,0,GVIDSCNSIZ);
          movmem(scnbuf,tmpbuf,GVIDSCNSIZ);
          culx=bulx;
          culy=buly;
          clrx=blrx;
          clry=blry;
          scn2mem(tmpbuf,0,GVIDSCNSIZ);
          if (opt == 'C') {
               explode(scntbl[MSCSCN],1,14,74,16);
          }
          else {
               explode(scntbl[MSCSCN],9,17,68,19);
          }
          hlpbox=1;
          while (done == 0) {
               c=getchc();
               if (hlpbox) {
                    mem2scn(tmpbuf,0,GVIDSCNSIZ);
                    hlpbox=0;
                    movmem(scnbuf,tmpbuf,GVIDSCNSIZ);
               }
               switch (c) {
               case CRSRUP:
                    if (culy-1 >= 0) {
                         for (ty=culy ; ty <= clry ; ty++) {
                              scn2scn(gvscnoff(culx,ty),
                                      gvscnoff(culx,(ty-1)),
                                      ((clrx-culx)+1)*2);
                         }
                         mem2scn(&scnbuf[gvscnoff(culx,clry)],
                                 gvscnoff(culx,clry),
                                 ((clrx-culx)+1)*2);
                         culy--;
                         clry--;
                    }
                    break;
               case CRSRDN:
                    if (clry < min(lasty,ylim-1)
                      && (clry != lasty-1 || clrx <= lastx)) {
                         for (ty=clry ; ty >= culy ; ty--) {
                              scn2scn(gvscnoff(culx,ty),
                                      gvscnoff(culx,(ty+1)),
                                      ((clrx-culx)+1)*2);
                         }
                         mem2scn(&scnbuf[gvscnoff(culx,culy)],
                                 gvscnoff(culx,culy),
                                 ((clrx-culx)+1)*2);
                         culy++;
                         clry++;
                    }
                    break;
               case CRSRLF:
                    if (culx-1 >= 0) {
                         for (ty=culy ; ty <= clry ; ty++) {
                              scn2scn(gvscnoff(culx,ty),
                                      gvscnoff(culx-1,ty),
                                      ((clrx-culx)+1)*2);
                              mem2scn(&scnbuf[gvscnoff(clrx,ty)],
                                      gvscnoff(clrx,ty),2);

                         }
                         culx--;
                         clrx--;
                    }
                    break;
               case CRSRRT:
                    if ((clry < lasty || clrx < lastx) && clrx < LRX) {
                         for (ty=culy ; ty <= clry ; ty++) {
                              scn2scn(gvscnoff(culx,ty),
                                      gvscnoff(culx+1,ty),
                                      ((clrx-culx)+1)*2);
                              mem2scn(&scnbuf[gvscnoff(culx,ty)],
                                      gvscnoff(culx,ty),2);

                         }
                         culx++;
                         clrx++;
                    }
                    break;
               case ' ':
                    if (opt == 'C') {
                         for (ty=0 ; ty <= (blry-buly) ; ty++) {
                              movmem(&blobuf[gvscnoff(bulx,(buly+ty))],
                                     &scnbuf[gvscnoff(culx,(culy+ty))],
                                     ((blrx-bulx)+1)*2);
                         }
                    }
                    break;
               case 13:
                    for (ty=0 ; ty <= (blry-buly) ; ty++) {
                         movmem(&blobuf[gvscnoff(bulx,(buly+ty))],
                                &scnbuf[gvscnoff(culx,(culy+ty))],
                                ((blrx-bulx)+1)*2);
                    }
                    done=1;
                    break;
               case ESC:
                    if (opt == 'M') {
                         movmem(blobuf,scnbuf,GVIDSCNSIZ);
                    }
                    else {
                         movmem(tmpbuf,scnbuf,GVIDSCNSIZ);
                    }
                    done=-1;
                    break;
               case TAB:
                    tx=clrx;
                    for (i=0 ; i < nelems(tabtbl) ; i++) {
                         if (clrx < tabtbl[i]) {
                              clrx=tabtbl[i];
                              break;
                         }
                    }
                    if (i == nelems(tabtbl)) {
                         clrx=LRX;
                    }
                    if (clry == lasty && clrx > lastx) {
                         clrx=lastx;
                    }
                    for (ty=culy ; ty <= clry ; ty++) {
                         scn2scn(gvscnoff(culx,ty),
                                 gvscnoff((culx+(clrx-tx)),ty),
                                 (tx-culx+1)*2);
                         mem2scn(&scnbuf[gvscnoff(culx,ty)],
                                 gvscnoff(culx,ty),
                                 (clrx-tx)*2);
                    }
                    culx+=(clrx-tx);
                    break;
               case BAKTAB:
                    tx=culx;
                    for (i=nelems(tabtbl) ; i >= 0 ; i--) {
                         if (culx > tabtbl[i]) {
                              culx=tabtbl[i];
                              break;
                         }
                    }
                    if (i == nelems(tabtbl)) {
                         culx=0;
                    }
                    for (ty=culy ; ty <= clry ; ty++) {
                         scn2scn(gvscnoff(tx,ty),
                                 gvscnoff(culx,ty),
                                 (clrx-tx+1)*2);
                         mem2scn(&scnbuf[gvscnoff(clrx-(tx-culx)+1,ty)],
                                 gvscnoff(clrx-(tx-culx)+1,ty),
                                 (tx-culx)*2);
                    }
                    clrx-=(tx-culx);
                    break;
               }
          }
          break;
     case 'E':
          for (ty=buly ; ty <= blry ; ty++) {
               for (tx=bulx ; tx <= blrx ; tx++) {
                    if (tvinxy(tx,ty) == NULL) {
                         scnbuf[gvscnoff(tx,ty)]=' ';
                         scnbuf[gvscnoff(tx,ty)+1]=0x07;
                    }
               }
          }
          break;
     case 'F':
          mem2scn(tmpbuf,0,GVIDSCNSIZ);
          explode(scntbl[MSCSCN],3,20,73,22);
          opt=getchc();
          mem2scn(tmpbuf,0,GVIDSCNSIZ);
          switch (toupper(opt)) {
          case 'E':
          case 'C':
               explode(scntbl[MSCSCN],21,11,52,13);
               do {
                    c=getchc();
               } while (c < 1 || 255 < c);
               if (c >= F1 && c <= F10) {
                    c=fkxtbl[fksinu][(c-F1)>>8];
               }
               for (ty=buly ; ty <= blry ; ty++) {
                    for (tx=bulx ; tx <= blrx ; tx++) {
                         if (tvinxy(tx,ty) == NULL) {
                              scnbuf[gvscnoff(tx,ty)]=c;
                              if (toupper(opt) == 'E') {
                                   scnbuf[gvscnoff(tx,ty)+1]=attr;
                              }
                         }
                    }
               }
               break;
          case 'A':
               for (ty=buly ; ty <= blry ; ty++) {
                    for (tx=bulx ; tx <= blrx ; tx++) {
                         if (tvinxy(tx,ty) == NULL) {
                              scnbuf[gvscnoff(tx,ty)+1]=attr;
                         }
                    }
               }
               break;
          case 'F':
               for (ty=buly ; ty <= blry ; ty++) {
                    for (tx=bulx ; tx <= blrx ; tx++) {
                         if (tvinxy(tx,ty) == NULL) {
                              scnbuf[gvscnoff(tx,ty)+1]&=0x70;
                              scnbuf[gvscnoff(tx,ty)+1]|=
                    ((attr&0x0F)|(attr&0x80));
                         }
                    }
               }
               break;
          case 'B':
               for (ty=buly ; ty <= blry ; ty++) {
                    for (tx=bulx ; tx <= blrx ; tx++) {
                         if (tvinxy(tx,ty) == NULL) {
                              scnbuf[gvscnoff(tx,ty)+1]&=(0x0F|0x80);
                              scnbuf[gvscnoff(tx,ty)+1]|=(attr&0x70);
                         }
                    }
               }
               break;
          default:
               break;
          }
     case ESC:
          break;
     }
     dsptvs();
     rfrscn();
}

VOID
joilin(VOID)
{
     struct txtvar *vptr;
     struct marker *mptr;
     INT splitx,i;

     if (y != lasty && empton(x,y) && (splitx=cbrkpt(LRX-x+1)) != 0) {
          movmem(scnbuf+gvscnoff(0,y+1),scnbuf+gvscnoff(x,y),splitx*2);
          for (vptr=tvars,i=0 ; i < nvars ; vptr++,i++) {
               if (vptr->line == y+1) {
                    if (vptr->startx < splitx) {
                         vptr->line--;
                         vptr->startx+=x;
                         vptr->endx+=x;
                    }
                    else {
                         vptr->startx-=splitx;
                         vptr->endx-=splitx;
                    }
               }
          }
          for (mptr=markers,i=0 ; i < nmarks ; mptr++,i++) {
               if (mptr->line == y+1) {
                    if (mptr->startx < splitx) {
                         mptr->line--;
                         mptr->startx+=x;
                         mptr->endx+=x;
                    }
                    else {
                         mptr->startx-=splitx;
                         mptr->endx-=splitx;
                    }
               }
          }
          if (splitx == LRX+1)  {
               rmlutl(y);
               if (y == lasty) {
                    lastx=LRX;
               }
          }
          else {
               movmem(scnbuf+gvscnoff(splitx,y+1),scnbuf+gvscnoff(0,y+1),
                    (LRX-splitx+1)*2);
               repmem(scnbuf+gvscnoff(LRX-splitx+1,y+1),"\40\7",splitx*2);
               if (y+1 == lasty) {
                    if (lastx < splitx) {
                         lasty--;
                         lastx=LRX-(splitx-lastx)+1;
                    }
                    else {
                         lastx-=splitx;
                    }
               }
               if (y+1 == finaly) {
                    if (finalx < splitx) {
                         finaly--;
                         finalx=LRX-(splitx-finalx)+1;
                    }
                    else {
                         finalx-=splitx;
                    }
               }
               if (y != lasty && empton(0,y+1)) {
                    rmlutl(y+1);
                    if (y == lasty) {
                         lastx=LRX;
                    }
               }
          }
          rfrscn();
     }
     else {
          printf("\7");
     }
}

VOID
divlin(VOID)
{
     struct txtvar *vptr;
     struct marker *mptr;
     INT i;

     if (y != ylim-1 && ((vptr=tvinxy(x,y)) == NULL || tvinxy(x-1,y) != vptr)
         && ((mptr=kminxy(x,y)) == NULL || kminxy(x-1,y) != mptr)) {
          inlutl(y+1);
          movmem(scnbuf+gvscnoff(x,y),scnbuf+gvscnoff(0,y+1),(LRX-x+1)*2);
          repmem(scnbuf+gvscnoff(x,y),"\40\7",(LRX-x+1)*2);
          for (vptr=tvars,i=0 ; i < nvars ; vptr++,i++) {
               if (vptr->line == y && vptr->startx >= x) {
                    vptr->line++;
                    vptr->startx-=x;
                    vptr->endx-=x;
               }
          }
          for (mptr=markers,i=0 ; i < nmarks ; mptr++,i++) {
               if (mptr->line == y && mptr->startx >= x) {
                    mptr->line++;
                    mptr->startx-=x;
                    mptr->endx-=x;
               }
          }
          if (y+1 == lasty) {
               lastx-=x;
          }
          if (y == finaly && finalx >= x) {
               finaly++;
               finalx-=x;
          }
          rfrscn();
     }
     else {
          printf("\7");
     }
}

INT
empton(
INT ex,
INT ey)
{
     INT i;

     if (finaly == ey && finalx >= ex) {
          return(0);
     }
     for (i=ex ; i <= LRX ; i++) {
          if (tvinxy(i,ey) != NULL || kminxy(i,ey) != NULL
           || scnbuf[gvscnoff(i,ey)] != ' ') {
               return(0);
          }
     }
     return(1);
}

INT
cbrkpt(
INT max)
{
     struct txtvar *vptr;
     struct marker *mptr;
     INT ix;

     for (ix=0 ; ix < max ; ix++) {
          if ((vptr=tvinxy(ix,y+1)) != NULL) {
               if (vptr->endx > max) {
                    break;
               }
               ix=vptr->endx;
          }
          else if ((mptr=kminxy(ix,y+1)) != NULL) {
               if (mptr->endx > max) {
                    break;
               }
               ix=mptr->endx;
          }
     }
     return(ix);
}

VOID
inslin(VOID)
{
     inlutl(y);
     if (y+1 != ylim) {
          y++;
     }
     rfrscn();
}

VOID
inlutl(
INT iy)
{
     INT i;
     struct marker *mptr;
     struct txtvar *vptr;

     for (i=0,mptr=markers ; i < nmarks ; i++,mptr++) {
          if (mptr->line == 24 && --nmarks != i) {
               movmem(mptr+1,mptr,(nmarks-(INT)(mptr-markers))*sizeof(struct marker));
          }
          else if (mptr->line >= iy) {
               mptr->line++;
          }
     }
     for (i=0,vptr=tvars ; i < nvars ; i++,vptr++) {
          if (vptr->line == 24 && --nvars != i) {
               movmem(vptr+1,vptr,(nvars-(INT)(vptr-tvars))*sizeof(struct txtvar));
          }
          else if (vptr->line >= iy) {
               vptr->line++;
          }
     }
     if (iy != LRY) {
          movmem(&scnbuf[gvscnoff(0,iy)],&scnbuf[gvscnoff(0,(iy+1))],(LRY-iy)*160);
          repmem(&scnbuf[gvscnoff(0,iy)],"\40\7",80*2);
     }
     else {
          repmem(&scnbuf[gvscnoff(0,iy)],"\40\7",80*2);
     }
     if (finaly == LRY) {
          finalx=finaly=-1;
     }
     else if (finaly >= iy) {
          finaly++;
     }
     if (lasty == LRY) {
          lastx=LRX;
     }
     else {
          lasty++;
     }
}

VOID
rmvlin(VOID)
{
     if (lasty != 0) {
          rmlutl(y);
          if (y == lasty && x > lastx) {
               x=lastx;
          }
          rfrscn();
     }
}

VOID
rmlutl(
INT ry)
{
     INT i;
     struct marker *mptr;
     struct txtvar *vptr;

     for (i=0,mptr=markers ; i < nmarks ; i++,mptr++) {
          if (mptr->line == ry) {
               delkm(mptr);
          }
          else if (mptr->line > ry) {
               mptr->line--;
          }
     }
     for (i=0,vptr=tvars ; i < nvars ; i++,vptr++) {
          if (vptr->line == ry && --nvars != i) {
               movmem(vptr+1,vptr,
                      (nvars-(INT)(vptr-tvars))*sizeof(struct txtvar));
          }
          else if (vptr->line > ry) {
               vptr->line--;
          }
     }
     if (dlbidx != MXRDLN-1) {
          movmem(&scnbuf[gvscnoff(0,ry)],dlines[++dlbidx],80*2);
     }
     else {
          movmem(dlines[1],dlines[0],(MXRDLN-1)*80*2);
          movmem(&scnbuf[gvscnoff(0,ry)],dlines[MXRDLN-1],80*2);
     }
     if (ry != LRY) {
          movmem(&scnbuf[gvscnoff(0,(ry+1))],&scnbuf[gvscnoff(0,ry)],(LRY-ry)*160);
          repmem(&scnbuf[gvscnoff(0,LRY)],"\40\7",80*2);
     }
     else {
          repmem(&scnbuf[gvscnoff(0,LRY)],"\40\7",80*2);
     }
     if (y == lasty) {
          y--;
          lastx=LRX;
     }
     if (ry == finaly) {
          finalx=finaly=-1;
     }
     else if (ry < finaly) {
          finaly--;
     }
     lasty--;
}

VOID
delkm(
struct marker *mptr)
{
     if (mptr != NULL && &markers[--nmarks] != mptr) {
          movmem(mptr+1,mptr,(nmarks-(INT)(mptr-markers))*sizeof(struct marker));
     }
}

VOID
rstlin(VOID)
{
     if (dlbidx != -1) {
          inslin();
          if (y != LRY) {
               y--;
               movmem(dlines[dlbidx--],&scnbuf[gvscnoff(0,y)],80*2);
          }
          else {
               movmem(dlines[dlbidx--],&scnbuf[gvscnoff(0,y)],80*2);
          }
     }
     rfrscn();
}

VOID
withcs(VOID)
{
     CHAR yans[4];

     strcpy(yans,(savwcs ? "Yes" : "No"));
     explodeto(scntbl[ERRSCN],0,8,19,13,30,9);
     if (edtval(30+11,13,sizeof(yans),yans,validyn,MCHOICE)) {
          savwcs=(yans[0] == 'Y');
     }
     rfrscn();
}

VOID
cvt2asc(VOID)
{
     INT i;
     CHAR *sp;
     CHAR yans[4];

     strcpy(yans,"Yes");
     explode(scntbl[ERRSCN],11,18,65,20);
     if (edtval(61,19,sizeof(yans),yans,validyn,MCHOICE) && yans[0] == 'Y') {
          for (sp=scnbuf,i=0 ; i < GVIDSCNSIZ/2 ; sp+=2,i++) {
               if (tvinxy(i%80,i/80) == NULL) {
                    if (*sp > 127) {
                         *sp='@';
                    }
                    *(sp+1)=0x07;
               }
          }
          finalx=finaly=-1;
     }
     rfrscn();
}

VOID
clrall(VOID)
{
     CHAR yans[4];

     strcpy(yans,"Yes");
     explode(scntbl[ERRSCN],11,21,64,23);
     if (edtval(60,22,sizeof(yans),yans,validyn,MCHOICE) && yans[0] == 'Y') {
          scblank(scnbuf,0x07);
          finalx=finaly=finalc=-1;
     }
     rfrscn();
}

VOID
setfxyc(VOID)
{
     CHAR yans[4];

     strcpy(yans,"Yes");
     explode(scntbl[TXVSCN],7,0,64,2);
     setatr(0x1E);
     locate(15,1);
     printf("%02d,%02d",x+1,y+1);
     setatr(attr);
     locate(26,1);
     printf("Color");
     if (edtval(59,1,sizeof(yans),yans,validyn,MCHOICE) && yans[0] == 'Y') {
          finalx=x;
          finaly=y;
          finalc=attr;
     }
     rfrscn();
}

#ifdef GCDOS
VOID
onlsim(VOID)
{
     static CHAR onlbaud[6]={"2400"};
     CHAR yans[4],tfn[7];

     if (undwin()) {
          return;
     }
     strcpy(yans,"Yes");
     explode(scntbl[TXVSCN],22,17,48,20);
     while (1) {
          if (!edtval(41,18,sizeof(onlbaud),onlbaud,validig,MULTIEX)) {
               break;
          }
          if (atol(onlbaud) >= 300 && atol(onlbaud) <= 38400L) {
               if (!edtval(41,19,sizeof(yans),yans,validyn,MULTIEX+MCHOICE)) {
                    break;
               }
               if (edtvalc != '\r') {
                    continue;
               }
               strcpy(tfn,"XXXXXX");
               animate(mktemp(tfn),atoi(onlbaud),(yans[0] == 'Y'));
               break;
          }
          printf("\7");
     }
     rfrscn();
}

#define BSIZE 4096            /* brkthu output buffer size for simulations */

VOID
animate(                           /* animate the playback of a msg        */
CHAR *ansfile,                     /*   filename of .ANS file              */
UINT speed,                        /*   baud rate for playback             */
UINT ansi)                         /*   1=enable ANSI ; 0=don't            */
{
     FILE *afp;
     CHAR *btubuf;
     CHAR *cptr,c;
     INT filedone=0;
     INT inmark=0;
     INT rc;

     saveans(ansfile);
     if ((afp=fopen(ansfile,FOPRB)) == NULL) {
          catastro("ANIMATION FILE NOT FOUND!");
     }
     if ((btubuf=getml(btulsz(1,2,BSIZE))) == NULL) {
          memcata();
     }
     if ((rc=btuitz(btubuf)) != 0) {
          catastro("BTUITZ returns %d",rc);
     }
     if ((rc=btudef(0,0x2F0,1)) != 0) {
          catastro("BTUDEF returns %d",rc);
     }
     btumon(0);
     btumxs(speed);
     btulfd(0,'\n');
     setatr(0x07);
     printf("\14");
     btucmd(0,ansi ? "[" : "]");
     ansion(ansi);
     while (!kbhit()) {
          if (!filedone && btuoba(0) > BSIZE/2) {
               if (mdfgets(tmpbuf,GVIDSCNSIZ,afp) == NULL) {
                    fclose(afp);
                    unlink(ansfile);
                    filedone=1;
               }
               else {
                    inmark=0;
                    for (cptr=tmpbuf ; *cptr != '\0' ; cptr++) {
                         if (*cptr == MARKCH) {
                              if (inmark) {
                                   inmark=0;
                                   movmem(cptr+1,cptr,strlen(cptr+1)+1);
                              }
                              else {
                                   movmem(cptr+2,cptr,strlen(cptr+2)+1);
                                   inmark=1;
                              }
                              cptr--;
                         }
                         else if (*cptr == TVARCH) {
                              *(cptr+2)-=32;
                              fmttxv(cptr,1);
                         }
                    }
                    btuxmt(0,tmpbuf);
               }
          }
          if ((c=btumds()) != '\0') {
               printf("%c",c);
          }
     }
     if (!filedone) {
          fclose(afp);
          unlink(ansfile);
     }
     getchc();
     btumon(-1);
     btuend();
     farfree(btubuf);
}
#endif // GCDOS

VOID
saveans(
CHAR *savnam)
{
     FILE *sfp;
     INT ix,iy,fx,fy;
     INT savatr,inkm4x=-1;
     CHAR *sp;
     struct marker *mptr;
     struct txtvar *vptr;

     if ((sfp=fopen(savnam,FOPWB)) == NULL) {
          catastro("Couldn't open %s for writing.\n",savnam);
     }
     if (!savwcs) {
          for (iy=0 ; iy <= lasty ; iy++) {
               if (is80lin(iy)) {
                    savwcs=1;
                    break;
               }
          }
     }
     if (savwcs) {
          fprintf(sfp,"\33[0m\33[2J");
          savatr=0x07;
     }
     else {
          savatr=~(*(scnbuf+1));
     }
     for (iy=0,fy=0 ; iy < lasty+1 ; iy++,fy++) {
          sp=scnbuf+gvscnoff(0,iy);
          if (is80lin(iy) && iy != lasty) {
               fprintf(sfp,"\33[s");
          }
          for (ix=0,fx=0 ; ix < 80 ; ix++,fx++,sp+=2) {
               if (inkm4x == -1 && (mptr=kminxy(ix,iy)) != NULL) {
                    fputc(MARKCH,sfp);
                    fputc(mptr->select,sfp);
                    inkm4x=mptr->endx;
               }
               if ((vptr=tvinxy(ix,iy)) != NULL) {
                    if (savatr != vptr->attr) {
                         fprintf(sfp,xlta2a(savatr,vptr->attr));
                         savatr=vptr->attr;
                    }
                    fputc(TVARCH,sfp);
                    fputc(justbl[(SHORT)vptr->just][0],sfp);
                    fputc(vptr->length+32,sfp);
                    fprintf(sfp,vptr->name);
                    fputc(TVARCH,sfp);
                    fx=(ix+=vptr->length-1);
                    sp+=(vptr->length-1)*2;
                    if (inkm4x != -1 && ix >= mptr->endx
               && (ix != LRX || mptr->startx != 0)) {
                         fputc(MARKCH,sfp);
                         inkm4x=-1;
                    }
                    if (iy == lasty && ix == lastx) {
                         break;
                    }
                    if (ix == 79) {
                         fprintf(sfp,"\33[u"STR_EOL);
                         savatr=~(*(scnbuf+1));
                    }
                    continue;
               }
               if ((*sp != ' ' && savatr != *(sp+1))
                 || (savatr&0x70) != (*(sp+1)&0x70)) {
                    fprintf(sfp,xlta2a(savatr,*(sp+1)));
                    savatr=*(sp+1);
               }
               if (inkm4x == -1 && iy != lasty && stoeol(ix,iy)) {
                    if (savatr&0x70) {
                         fprintf(sfp,"\33[K");
                    }
                    fprintf(sfp,STR_EOL);
                    break;
               }
               if (iy == lasty && ix >= lastx) {
                    break;
               }
               fputc(*sp,sfp);
               if (inkm4x != -1 && mptr->endx == ix) {
                    if (ix != LRX || mptr->startx != 0) {
                         fputc(MARKCH,sfp);
                    }
                    inkm4x=-1;
                    fprintf(sfp,xlta2a(~savatr,savatr));
               }
               if (ix == 79) {
                    fprintf(sfp,"\33[u"STR_EOL);
                    savatr=~(*(scnbuf+1));
               }
          }
     }
     if (finalx != -1) {
          if (fx == 79) {
               fx=-1;
               fy++;
          }
          if ((fy-finaly-1) != 0) {
               fprintf(sfp,"\33[%dA",fy-finaly-1);
          }
          finalx--;
          if ((fx-finalx) != 0) {
               fprintf(sfp,"\33[%d%c",abs(fx-finalx),(fx-finalx < 0 ? 'C' : 'D'));
          }
          finalx++;
          if (finalc != savatr) {
               fprintf(sfp,xlta2a(savatr,finalc));
          }
     }
     fclose(sfp);
}

VOID
fmttxv(
CHAR *cptr,
INT con)
{
     INT fldsiz,blanks;
     CHAR *data,*contin,*dptr;
     static CHAR datbuf[81];

     data=cptr+3;
     for (dptr=data ; *dptr != TVARCH ; dptr++) {
     }
     *dptr='\0';
     fldsiz=(INT)(dptr-data);
     contin=dptr+1;
     switch (*(cptr+1)) {
     case 'N':
          movmem(data,datbuf,fldsiz);
          datbuf[fldsiz]='\0';
          break;
     case 'C':
          setmem(datbuf,80,' ');
          blanks=max(0,*(cptr+2)-fldsiz)/2;
          movmem(data,datbuf+blanks,fldsiz);
          fldsiz=*(cptr+2);
          datbuf[fldsiz]='\0';
          break;
     case 'R':
          fldsiz=*(cptr+2);
          sprintf(datbuf,"%*.*s",fldsiz,fldsiz,data);
          break;
     case 'L':
          fldsiz=*(cptr+2);
          sprintf(datbuf,"%-*.*s",fldsiz,fldsiz,data);
          break;
     }
     if (con) {
          movmem(contin,cptr+fldsiz,strlen(contin)+1);
     }
     else {
          cptr[fldsiz]='\0';
     }
     movmem(datbuf,cptr,fldsiz);
}

VOID
getload(VOID)
{
     static CHAR lfname[40];

     lfname[0]='\0';
     explodeto(scntbl[ERRSCN],20,11,79,13,10,11);
     if (edtval(29,12,sizeof(lfname),lfname,valfln,needupc() ? ALLCAPS : 0)) {
          mdload(0,lfname);
     }
     x=y=0;
     rfrscn();
}

GBOOL
valfln(                            /* is this a valid file name?           */
INT c,                             /*   character to add                   */
CHAR *stg)                         /*   name so far                        */
{
     return(c == '\\' || c == ':' || isfiln(c,stg));
}

VOID
rfrlin(VOID)
{
     if (y != 0) {
          mem2scn(scnbuf+gvscnoff(0,y-1),gvscnoff(0,y-1),80*2);
     }
     mem2scn(scnbuf+gvscnoff(0,y),gvscnoff(0,y),80*2);
     if (y == lasty) {
          adjbdr();
     }
     shofxyc();
     updqrf();
     locate(x,y);
}

VOID
rfrscn(VOID)                       /* refresh drawing screen               */
{
     mem2scn(scnbuf,0,GVIDSCNSIZ);
     adjbdr();
     if (qrftog) {
          shwqrf();
     }
     shofxyc();
     locate(x,y);
}

VOID
adjbdr(VOID)
{
     if (lastx < LRX && lasty <= LRY) {
          mem2scn("Ú\7",gvscnoff(lastx+1,lasty),2);
          if (lastx < LRX-1) {
               scnputw(gvscnoff(lastx+2,lasty),'Ä','\7',LRX-1-lastx);
          }
     }
     if (lasty != ylim-1 && lasty < LRY) {
          scnputw(gvscnoff(0,lasty+1),'Ä','\7',lastx+1);
          if (lastx < LRX) {
               mem2scn("Ù\7",gvscnoff(lastx+1,lasty+1),2);
               if (lastx < LRX-1) {
                    scnputw(gvscnoff(lastx+2,lasty+1),'\40','\7',LRX-lastx-1);
               }
          }
          else {
               if (lasty != ylim-2 && lasty < LRY-1) {
                    scnputw(gvscnoff(0,lasty+2),'\40','\7',80);
               }
          }
     }
}

VOID
shofxyc(VOID)
{
     if (finalx != -1) {
          locate(finalx,finaly);
          setatr(finalc);
          printf("%c",1);
          setatr(attr);
     }
}

VOID
shwkmk(VOID)                       /* show key marked areas of screen      */
{
     struct marker *mptr;
     INT i,j;

     for (i=0,mptr=markers ; i < nmarks ; i++,mptr++) {
          for (j=mptr->startx ; j <= mptr->endx ; j++) {
               scnputc(gvscnoff(j,mptr->line)+1,0x87);
          }
     }
}

VOID
hidqrf(VOID)                       /* hide quick reference line            */
{
     qrftog=0;
     ylim=25;
     rfrscn();
}

VOID
intro(VOID)                        /* exploding window introduction block  */
{
     explode(scntbl[INTSCN],8,4,69,15);
}

INT
mdload(
INT isbuff,
CHAR *fnorbf)
{
#define REGSTT      1         /* regular state: check for 1, 27, or 255    */
#define ISASTT      2         /* is ansi? state: check for [               */
#define RDASTT      3         /* reading ansi state                        */
#define MSCSTT      4         /* getting marker select character state     */
#define TVJSTT      5         /* reading text variable justification state */
#define TVLSTT      6         /* reading text variable length state        */
#define TVNSTT      7         /* reading text variable name state          */

     struct marker *mptr=NULL;
     struct txtvar *vptr=NULL;
     CHAR ansstg[16],vname[TVRSIZ];
     INT c,i,state=REGSTT,inmark=0,ansidx,vnmidx;
     INT oldlx,oldly;
     CHAR *bufptr;
     FILE *fp;

     clrfxyc();
     cldatr=0x07;
     savwcs=lx=ly=nmarks=nvars=lastx=lasty=0;
     scblank(scnbuf,0x07);
     if (isbuff) {
          bufptr=fnorbf;
     }
     else {
          strcpy(filnam,fnorbf);
          if ((fp=fopen(filnam,FOPRB)) == NULL) {
               return(0);
          }
     }
     ldsp=scnbuf;
     while (1) {
          if (isbuff) {
               if ((c=*bufptr++) == '\0') {
                    break;
               }
          }
          else {
               if ((c=getc(fp)) == EOF) {
                    break;
               }
          }
          if (c == '\r' || c == 26) {
               continue;
          }
          ldsp=&scnbuf[gvscnoff(lx,(ly == 25 ? 24 : ly))];
          switch (state) {
          case REGSTT:
               switch (c) {
               case 12:
                    savwcs=1;
                    break;
               case ESC:
                    state=ISASTT;
                    break;
               case MARKCH:
                    if (inmark) {
                         inmark=0;
                         mptr->endx=(lx == 0 ? LRX : lx-1);
                    }
                    else {
                         mptr=&markers[nmarks++];
                         mptr->line=ly;
                         mptr->startx=lx;
                         inmark=1;
                         state=MSCSTT;
                    }
                    break;
               case TVARCH:
                    vptr=&tvars[nvars++];
                    vptr->line=ly;
                    vptr->startx=lx;
                    vptr->attr=cldatr;
                    state=TVJSTT;
                    break;
               default:
                    if (inmark && c == '\n') {
                         inmark=0;
                         mptr->endx=LRX;
                    }
                    if (c == '\n' && ly < 24) {
                         lastx=lx=0;
                         ly++;
                         lasty=ly;
                    }
                    else {
                         clrfxyc();
                         ldabyt(c);
                    }
               }
               break;
          case ISASTT:
               if (c == '[') {
                    ansidx=0;
                    state=RDASTT;
               }
               else {
                    ldabyt(ESC);
                    ldabyt('[');
                    state=REGSTT;
               }
               break;
          case RDASTT:
               ansstg[ansidx++]=c;
               if (isalpha(c) || c == '[') {
                    ansstg[ansidx]='\0';
                    switch (c) {
                    case 'm':
                         cldatr=dwaatr(cldatr,ansstg);
                         finalc=cldatr;
                         break;
                    case 'H':
                    case 'f':
                    case 'A':
                    case 'B':
                    case 'C':
                    case 'D':
                         dwamov(ansstg);
                         break;
                    case 'J':
                         savwcs=1;
                         scblank(scnbuf,0x07);
                         break;
                    case 's':
                         oldlx=lx;
                         oldly=ly;
                         break;
                    case 'u':
                         lx=oldlx;
                         ly=oldly;
                         break;
                    case 'K':
                         for (i=lx ; i < 80 ; i++,ldsp+=2) {
                              *ldsp=' ';
                              *(ldsp+1)=cldatr;
                         }
                         break;
                    case '[':
                    default:
                         ldabyt(ESC);
                         ldabyt('[');
                         for (i=0 ; i < ansidx ; i++) {
                              ldabyt(ansstg[i]);
                         }
                    }
                    state=REGSTT;
               }
               break;
          case MSCSTT:
               mptr->select=c;
               state=REGSTT;
               break;
          case TVJSTT:
               vptr->just=(INT)((CHAR *)strchr(justlt,c)-justlt);
               state=TVLSTT;
               break;
          case TVLSTT:
               vptr->length=c-32;
               vnmidx=0;
               state=TVNSTT;
               break;
          case TVNSTT:
               if (c == TVARCH) {
                    vname[vnmidx]='\0';
                    strcpy(vptr->name,vname);
                    vptr->endx=vptr->startx+vptr->length-1;
                    ptvons(vptr);
                    lastx=(lx+=vptr->length);
                    state=REGSTT;
               }
               else {
                    vname[vnmidx++]=c;
               }
               break;
          }
     }
     if (inmark) {
          mptr->endx=LRX;
     }
     if (!isbuff) {
          fclose(fp);
     }
     if (finalx != -1) {
          if ((y=finaly) > lasty) {
               lasty=finaly;
          }
          if ((x=finalx) > lastx  && finaly == lasty) {
               lastx=finalx;
          }
     }
     return(1);
}

INT
dwaatr(
INT catr,
CHAR *stg)
{
     CHAR *sptr;
     INT val;

     sptr=stg;
     while (*sptr != '\0') {
          for (val=0 ; isdigit(*sptr) ; sptr++) {
               val=(val*10)+(*sptr-'0');
          }
          switch (val) {
          case 0:
               catr=0x07;
               break;
          case 1:
               catr|=0x08;
               break;
          case 5:
               catr|=0x80;
               break;
          case 7:
               catr&=0xC8;
               break;
          case 30:
          case 31:
          case 32:
          case 33:
          case 34:
          case 35:
          case 36:
          case 37:
               catr=(catr&0xF8)+astf[val-30];
               break;
          case 40:
          case 41:
          case 42:
          case 43:
          case 44:
          case 45:
          case 46:
          case 47:
               catr=(catr&0x8F)+(astf[val-40]<<4);
               break;
          }
          sptr++;
     }
     return(catr);
}

VOID
dwamov(
CHAR *stg)
{
     INT tmpx,tmpy,val,val1=0;
     CHAR *sptr;

     tmpx=lx;
     tmpy=ly;
     if (psbend) {
          tmpy-=1;
          tmpx=80;
          psbend=0;
     }
     sptr=stg;
     while (*sptr != '\0') {
          for (val=0 ; isdigit(*sptr) ; sptr++) {
               val=(val*10)+(*sptr-'0');
          }
          if (tmpx == 80 && *sptr >= 'A' && *sptr <= 'D') {
               tmpx=0;
               tmpy++;
          }
          val=val == 0 ? 1 : val;
          switch (*sptr) {
          case ';':
               val1=val;
               break;
          case 'H':
          case 'f':
               if (val1 != 0) {
                    tmpy=val1-1;
                    tmpx=val-1;
               }
               else {
                    tmpy=val-1;
                    tmpx=0;
               }
               break;
          case 'A':
               tmpy-=val;
               break;
          case 'B':
               tmpy+=val;
               break;
          case 'C':
               if (!psbend) {
                    tmpx-=1;
               }
               tmpx+=(val+1);
               break;
          case 'D':
               if (!psbend) {
                    tmpx-=1;
               }
               tmpx-=(val-1);
          }
          sptr++;
     }
     if (tmpx >= 0 && tmpx <= LRX && tmpy >= 0 && tmpy <= LRY) {
          lx=finalx=tmpx;
          ly=finaly=tmpy;
     }
}

VOID
ldabyt(
INT c)
{
     *ldsp=c;
     *(ldsp+1)=cldatr;
     if (ly == 25) {
          lx=79;
          ly--;
     }
     lastx=lx;
     lasty=ly;
     if (++lx == 80) {
          lx=0;
          ly++;
          psbend=1;
     }
     else {
          psbend=0;
     }
     ldsp+=2;
}

#if defined( GCWINNT )

VOID
initWinHelp(                       /* set WinHelp file name and help id    */
const char *fname,                 /*   path and name (with .hlp extension */
ULONG id)                          /*   help file context id               */
{
     ASSERT(fname != NULL);
     helpFn=fname;
     helpId=id;
}


VOID
closeWinHelp(VOID)                 /* quit WinHelp IFF we're using it      */
{
     HWND      hwnd;

     if (usingWinHelp) {
          hwnd=GetMainWindow();

          if (hwnd != NULL) {
               WinHelp(hwnd,helpFn,HELP_QUIT,0);
          }

          usingWinHelp=FALSE;
     }
}


static HWND                        /*   main HWND or NULL                  */
GetMainWindow(VOID)                /* get console's main window handle     */
{
     HWND      hwnd=NULL;
     char      titleBuf[256];

     if (GetConsoleTitle(titleBuf,sizeof(titleBuf)) > 0) {
          hwnd=FindWindow(NULL,titleBuf);
     }

     return( hwnd );
}

static GBOOL                       /*   TRUE if file exists, else FALSE    */
exists(                            /* check for existence of a given file  */
const char *fname)                 /*   name of the file in question       */
{
     return(isfile(fname));
}

#endif


VOID
clrfxyc(VOID)
{
     finalx=-1;
     finaly=-1;
}

INT
stoeol(
INT lx,
INT ly)
{
     INT batr;

     if (ly == lasty) {
          return(lx > lastx);
     }
     batr=(scnbuf[gvscnoff(lx,ly)+1]&0x70);
     for ( ; lx < 80 ; lx++) {
          if (scnbuf[gvscnoff(lx,ly)] != ' '
           || (scnbuf[gvscnoff(lx,ly)+1]&0x70) != batr) {
               return(0);
          }
     }
     return(1);
}

INT
is80lin(
INT line)
{
     return(scnbuf[gvscnoff(79,line)] != ' ' || kminxy(79,line) != NULL);
}

INT
endscn(
INT fromy)
{
     return(fromy > lasty);
}

CHAR *
xlta2a(
INT old,
INT newval)
{
     static CHAR retval[16];

     strcpy(retval,"\33[");
     if ((old&0x88) != (newval&0x88)) {
          if (((old^newval)&old)&0x88) {
               strcat(retval,"0;");
               old=0x07;
          }
          if (((old^newval)&newval)&0x08) {
               strcat(retval,"1;");
          }
          if (((old^newval)&newval)&0x80) {
               strcat(retval,"5;");
          }
     }
     if ((old&0x07) != (newval&0x07)) {
          strcat(retval,spr("%d;",30+astf[newval&0x07]));
     }
     if ((old&0x70) != (newval&0x70)) {
          strcat(retval,spr("%d;",40+astf[(newval>>4)&0x07]));
     }
     retval[strlen(retval)-1]='m';
     return(retval);
}

VOID
shfllf(VOID)
{
     struct txtvar *vptr;
     struct marker *mptr;
     INT i;

     for (vptr=tvars,i=0 ; i < nvars ; vptr++,i++) {
          if (vptr->line == y && vptr->startx > x) {
               vptr->startx--;
               vptr->endx--;
          }
     }
     for (mptr=markers,i=0 ; i < nmarks ; mptr++,i++) {
          if (mptr->line == y && mptr->startx > x) {
               mptr->startx--;
               mptr->endx--;
          }
          else if (mptr->line == y && x >= mptr->startx && x <= mptr->endx) {
               if (mptr->startx == mptr->endx) {
                    delkm(mptr);
               }
               else {
                    mptr->endx--;
               }
          }
     }
     if (x != LRX) {
          movmem(&scnbuf[gvscnoff(x+1,y)],&scnbuf[gvscnoff(x,y)],(LRX-x)*2);
     }
     scnbuf[gvscnoff(LRX,y)]=' ';
     scnbuf[gvscnoff(LRX,y)+1]=0x07;
     if (y == lasty) {
          lastx--;
     }
}

VOID
movcur(                            /* move cursor from current location    */
INT dx,                            /*   change X position by this much     */
INT dy)                            /*   change Y position by this much     */
{
     x+=dx;
     y+=dy;
     if (x > LRX) {
          x=LRX;
     }
     if (x < ULX) {
          x=ULX;
     }
     if (y > min(ylim-1,lasty)) {
          y=min(ylim-1,lasty);
     }
     if (y < ULY) {
          y=ULY;
     }
     if (y == lasty && x > lastx) {
          x=lastx+1;
     }
     updqrf();
}

VOID
updqrf(VOID)
{
     if (qrftog) {
          locate(24,24);
          setatr(QRFATR);
          printf("%02d,%02d",x+1,y+1);
          locate(32,24);
          setatr(attr);
          printf(" Color ");
     }
}

VOID
jmp2eol(VOID)
{
     for (x=LRX ; x != 0 ; x--) {
          if (*(scnbuf+gvscnoff(x,y)) != ' ') {
               break;
          }
     }
     if (scnbuf[gvscnoff(x,y)] != ' ' && (y != lasty || x != lastx)) {
          x=min(x+1,LRX);
     }
}

VOID
putit(                             /* put a char (w/ attr) on scn & in buf */
INT c)
{
     struct txtvar *vptr;
     struct marker *mptr;
     INT i;

     if ((vptr=tvinxy(x,y)) != NULL) {
          if (!insmod || tvinxy(x-1,y) == vptr) {
               printf("\7");
               return;
          }
     }
     if (insmod && x != LRX) {
          for (vptr=tvars,i=0 ; i < nvars ; vptr++,i++) {
               if (vptr->line == y && vptr->startx >= x) {
                    if (vptr->endx+1 > LRX) {
                         return;
                    }
               }
          }
          for (vptr=tvars,i=0 ; i < nvars ; vptr++,i++) {
               if (vptr->line == y && vptr->startx >= x) {
                    vptr->startx++;
                    vptr->endx++;
               }
          }
          for (mptr=markers,i=0 ; i < nmarks ; mptr++,i++) {
               if (mptr->line == y && mptr->startx >= x) {
                    if (mptr->startx >= x) {
                         if (++mptr->startx > LRX) {
                              delkm(mptr);
                         }
                    }
                    else if (mptr->line == y && x >= mptr->startx
                             && x <= mptr->endx) {
                         if (mptr->startx == mptr->endx) {
                              delkm(mptr);
                         }
                         else {
                              mptr->endx--;
                         }
                    }
               }
               if (mptr->endx >= x) {
                    mptr->endx=min(mptr->endx+1,LRX);
               }
          }
          movmem(scnbuf+gvscnoff(x,y),scnbuf+gvscnoff(x+1,y),(LRX-x)*2);
          if (y == lasty && lastx != LRX) {
               lastx++;
          }
     }
     else if (y == lasty && x >= lastx && x != LRX) {
          lastx++;
     }
     scnbuf[gvscnoff(x,y)]=c;
     scnbuf[gvscnoff(x,y)+1]=attr;
     rfrlin();
     movcur(CURRT);
}

VOID
setbdr(
INT color)
{
#ifdef GCDOS
     union REGS xregs;

     xregs.x.ax=0x1001;
     xregs.x.bx=(color<<8);
     int86(0x10,&xregs,&xregs);
     xregs.x.ax=0x0B00;
     xregs.x.bx=color;
     int86(0x10,&xregs,&xregs);
#else
     (VOID)color;
#endif // GCDOS
}

GBOOL
blowoff(VOID)                      /* ask user if ok to blow off changes   */
{
     CHAR yonans[YONSIZ];

     strcpy(yonans,"No");
     explodeto(scntbl[COLSCN],0,18,25,23,26,10);
     if (edtval(26+16,14,YONSIZ,yonans,validyn,MCHOICE) && yonans[0] == 'Y') {
          return(TRUE);
     }
     rfrscn();
     return(FALSE);
}
