/***************************************************************************
 *                                                                         *
 *   EMULATE.C                                                             *
 *                                                                         *
 *   Copyright (c) 1992-1997 Galacticomm, Inc.      All Rights Reserved.   *
 *                                                                         *
 *   Emulation screen support module.                                      *
 *                                                                         *
 *                                            - Robert A. Rose 02/04/92    *
 *                                                                         *
 ***************************************************************************/

#include "gcomm.h"
#include "majorbbs.h"
#include "wgsmajor.h"
#include "oprlow.h"

#define FILREV "$Revision: 8 $"

extern INT audhdl;            /* handle for the audit screen               */
INT emful;                    /* handle for the full remote emulate screen */
extern INT stahdl;            /* handle for the graph screen               */
INT ehdl;                     /* handle for the emulation screen           */

VOID emulupd(VOID);
UINT emulkey(UINT scncod);
UINT emufkey(UINT scncod);
VOID oprmks(INT chr);
VOID emuchn(INT chn2em);
VOID lvchat(VOID);
VOID winupdt(VOID);
VOID set4ed(INT rstw);
VOID rst4ed(VOID);

static
FILE *elogfp;                 /* file handle for emulated session          */

INT chnemd=-1,                /* channel currently being emulated (-1=none)*/
    rmtsys=-1,                /* remote sysop emulation channel (-1 if no) */
    ltoggl;                   /* log-emu-session-to-disk toggle            */
INT emshue=0x50,              /* emulation status display attribute code   */
    emthue=0x0A,              /* emulation text display attribute code     */
    emhhue=0x0D;              /* emulation help-title display attr code    */

CHAR *tmpscn1,                     /* temporary screen buffer for vidmov() */
     *tmpscn2;                     /* temporary screen buffer for vidmov() */

struct curatr intansb;             /* interrupted ansi save block          */
struct curatr emuansb;             /* ansi state save block                */

struct scrnid emulscn={
     "wgsem.bin",                  /* screen filename                      */
     3040,
     ALT_E,                        /* select scan code (from main screen)  */
                                   /* ala 'Keyboard Accelerator'           */
     NULL,                         /* screen going away routine            */
     NULL,                         /* screen repaint routine               */
     emulkey,                      /* key handler routine                  */
     NULL,                         /* occasional update routine            */
     0,                            /* seconds between occasional updates   */
     0,                            /* seconds to go before next update     */
     NULL,                         /* called every cycle when displayed    */
     1,1,                          /* current cursor position on screen    */
     1,                            /* does cursor move?                    */
     1,                            /* should screen scroll?                */
     1,1,70,17,                    /* scrolling for window (default)       */
     NULL,                         /* perm. save buffer                    */
     NULL                          /* current location of screen           */
};

struct scrnid emfuscn={
     NULL,                         /* screen filename                      */
     4000,
     0,                            /* select scan code (from main screen)  */
                                   /* ala 'Keyboard Accelerator'           */
     NULL,                         /* screen going away routine            */
     NULL,                         /* screen repaint routine               */
     emufkey,                      /* key handler routine                  */
     NULL,                         /* occasional update routine            */
     0,                            /* seconds between occasional updates   */
     0,                            /* seconds to go before next update     */
     NULL,                         /* called every cycle when displayed    */
     1,1,                          /* current cursor position on screen    */
     1,                            /* does cursor move?                    */
     1,                            /* should screen scroll?                */
     0,0,79,23,                    /* scrolling for window (default)       */
     NULL,                         /* perm. save buffer                    */
     NULL                          /* current location of screen           */
};

VOID
emuchn(chn2em)                     /* enter current channel emulation      */
INT chn2em;
{
     if (chn2em != chnemd) {
          chnemd=chn2em;
          actvscn(ehdl);
          locate(21,0);
          sstatr(0x70);
          printf("%02.2x",channel[chn2em]);
          locate(1,3);
          sstatr(0x0a);
          set4ed(0);
          locate(0,0);
          ansion(1);
          sstatr(emthue);
          printf("\33[1;24r\14");
          scnids[emful].cx=curcurx();
          scnids[emful].cy=curcury();
          locate(0,24);
          sstatr(0x70);
          printf("          Emulating channel %02.2x  -  Hit ESC to return "
           "to main screen          ",channel[chnemd]);
          locate(0,2);
          sstatr(0x0a);
          rst4ed();
          btumon(chnemd);
     }
     if (chnemd >= 0
       && usroff(chnemd)->usrcls == VACANT
       && (usroff(chnemd)->flags&NOHDWE)) {
          btuinj(chnemd,RING);
     }
     dftbel(0);
     winupdt();
}

VOID
emulupd(VOID)                      /* update emulation screens             */
{
     INT c,i;
     CHAR *ptr;
     struct user *uptr;
     static CHAR dsbuf[40];

     if ((c=btumds()) != 0) {
          set4ed(1);
          do {
               dsbuf[0]=c;
               for (i=1,ptr=dsbuf+1 ; i < sizeof(dsbuf)-1 ; i++) {
                    if ((*ptr++=btumds()) == 0) {
                         break;
                    }
               }
               printf("%s",dsbuf);
               if (rmtsys >= 0) {
                    btuxct(rmtsys,i,dsbuf);
                    uptr=usroff(rmtsys);
                    uptr->flags|=ACTIVE;
                    uptr->nazapc=0;
               }
               if (ltoggl) {
                    fprintf(elogfp,"%s",dsbuf);
               }
          } while ((c=btumds()) != 0);
          rst4ed();
          winupdt();
     }
}

UINT
emulkey(
UINT scncod)                       /* keystroke hit on little screen       */
{
     switch (scncod) {
     case TAB:
          scn2mai(stahdl);
          break;
     case BAKTAB:
          scn2mai(audhdl);
          break;
     case ESC:
          scn2mai(emful);
          break;
     default:
          if (skcipg || (scncod >= F1 && scncod <= F10)) {
               return(scncod);
          }
          return(emufkey(scncod));
     }
     return(0);
}

UINT
emufkey(
UINT scncod)                       /* keystroke hit on full screen         */
{
     switch (scncod) {
     case ESC:
          scn2mai(ehdl);
          break;
     case ALT_L:                   /* Toggle Log file open/close           */
          setwin(scnids[emful].location,0,0,79,23,1);
          locate(35,24);
          sstatr(0x70);
          if (ltoggl^=1) {
               if ((elogfp=fopen("emubbs.log",FOPAB)) == NULL) {
                    printf("\7");
                    ltoggl^=1;
               }
               else {
                    printf("Logging session to file: %s ",fnmcse("emubbs.log"));
                    fprintf(elogfp,"Log activated at %s %s\r\n\r\n",
                            nctime(now()),ncedat(today()));
               }
          }
          else {
               fprintf(elogfp,"\r\n\r\nLog terminated at %s %s\r\n",
                       nctime(now()),ncedat(today()));
               fclose(elogfp);
               printf("Hit ESC to return to main screen    ");
          }
          rstloc();
          rstwin();
          break;
     case SHIFT+F2:
          if (chnemd >= 0) {
               curusr(chnemd);
               if (usrptr->flags&OPCHAT) {
                    lvchat();
               }
               else if (usrptr->usrcls > SUPIPG) {
                    entcht();
               }
          }
          break;
     case SHIFT+F10:
          btuinj(chnemd,RING);
          break;
     default:
          if (scncod&eurmsk) {
               btumks(scncod);
          }
          else {
               switch (scncod) {
               case CRSRUP:
                    oprmks('A');
                    break;
               case CRSRDN:
                    oprmks('B');
                    break;
               case CRSRRT:
                    oprmks('C');
                    break;
               case CRSRLF:
                    oprmks('D');
                    break;
               case HOME:
                    oprmks('H');
                    break;
               case END:
                    oprmks('K');
                    break;
               case DEL:
                    btumks(0x7f);
                    break;
               case TAB:      /* ignore these due to crazy property of     */
               case BAKTAB:   /* summary that causes endless loops         */
                    break;
               default:
                    if (mainhdl == emful && scncod >= F1 && scncod <= F10) {
                         break;
                    }
                    return(scncod);
               }
          }
          break;
     }
     return(0);
}

VOID
oprmks(chr)                        /* emit an ANSI cursor-movement string  */
INT chr;
{
     btumks('\33');
     btumks('[');
     btumks(chr);
}

VOID
emdisp(                            /* emulation display for operator       */
CHAR *stg)                         /*   string to display                  */
{
     set4ed(1);
     sstatr(emthue);
     ansion(1);
     sstatr(emthue);
     printf("\n");
     sstatr(emshue);
     printf("\33[1;24r");
     printf(stg);
     sstatr(emthue);
     printf("\n");
     scnids[emful].cx=curcurx();
     scnids[emful].cy=curcury();
     rst4ed();
     winupdt();
}

VOID
set4ed(INT rstw)                   /* prepare to display on emulation      */
{
     if (emful != mainhdl) {
          saveworld(&intansb);
     }
     if (rstw) {
          restworld(&emuansb);
     }
     setwin(scnids[emful].location,0,0,79,23,1);
     dftbel(0);
     cursact(emful == mainhdl);
}

VOID
rst4ed(VOID)                       /* reset things from emulation display  */
{
     cursact(0);
     scnids[emful].cx=curcurx();
     scnids[emful].cy=curcury();
     saveworld(&emuansb);
     if (emful != mainhdl) {
          restworld(&intansb);
     }
     ansion(0);
}

VOID
lvchat(VOID)                       /* exit user from sysop chat mode       */
{
     othusn=chnemd;
     usroff(othusn)->flags&=~(OPCHAT+NOINJO+NOZAP);
     setmbk(mjrmb);
     prfmsg(ENDCHT);
     injoth();
     clrprf();
     rstmbk();
     btucli(othusn);
     btumil(othusn,DFTIMX);
}

VOID
winupdt(VOID)                      /* update little window from full thing */
{
     VOID vidmov(CHAR *,INT,INT,INT,INT,CHAR *,INT,INT);
     static INT x1=0,y1=0;
     CHAR *src,*dst;
     INT didit=0;

     src=scnids[emful].location;
     dst=scnids[ehdl].location;
     while (scnids[emful].cx >= x1+70) {
          x1++;
          vidmov(src,x1,y1,70,17,dst,1,1);
          didit=1;
     }
     while (scnids[emful].cx < x1) {
          x1--;
          vidmov(src,x1,y1,70,17,dst,1,1);
          didit=1;
     }
     while (scnids[emful].cy >= y1+17) {
          y1++;
          vidmov(src,x1,y1,70,17,dst,1,1);
          didit=1;
     }
     while (scnids[emful].cy < y1) {
          y1--;
          vidmov(src,x1,y1,70,17,dst,1,1);
          didit=1;
     }
     if (!didit) {
          vidmov(src,x1,y1,70,17,dst,1,1);
     }
     scnids[ehdl].cx=1+scnids[emful].cx-x1;
     scnids[ehdl].cy=1+scnids[emful].cy-y1;
     if (ehdl == mainhdl) {
          cursact(1);
          locate(scnids[ehdl].cx,scnids[ehdl].cy);
     }
}

VOID
entcht(VOID)                       /* enter sysop chat mode now            */
{
     INT i;

     if (usrptr->flags&ISGCSU) {   /* don't chat if C/S user               */
          return;
     }
     usrptr->flags|=(OPCHAT+NOINJO+NOZAP);
     usrptr->flags&=~CONCEX;
     if (usrptr->flags&X2MAIN) {
          for (i=0 ; i < XTRIES && usrptr->state != 0 ; i++) {
               strcpy(input,"x");
               margc=1;
               margv[0]=input;
               hdlinp();
               btuclo(usrnum);
          }
     }
     btuclo(usrnum);
     setmbk(mjrmb);
     prfmsg(BGNCHT);
     btuxmt(usrnum,prfbuf);
     clrprf();
     rstmbk();
     btucli(usrnum);
     btumil(usrnum,-(usaptr->scnwid-1));
}

VOID
vidmov(
CHAR *b1,
INT x1,
INT y1,
INT dltx,
INT dlty,
CHAR *b2,
INT x2,
INT y2)
{
     INT i;

     if (b1 == NULL) {
          scn2mem(tmpscn1,0,GVIDSCNSIZ);
     }
     else {
          movmem(b1,tmpscn1,GVIDSCNSIZ);
     }
     if (b2 == NULL) {
          scn2mem(tmpscn2,0,GVIDSCNSIZ);
     }
     else {
          movmem(b2,tmpscn2,GVIDSCNSIZ);
     }
     for (i=0 ; i < dlty ; i++) {
          movmem(tmpscn1+((y1+i)*160)+(x1*2),tmpscn2+((y2+i)*160)+(x2*2),2*dltx);
     }
     if (b2 == NULL) {
          mem2scn(tmpscn2,0,GVIDSCNSIZ);
     }
     else {
          memcpy(b2,tmpscn2,GVIDSCNSIZ);
     }
}
