/***************************************************************************
 *                                                                         *
 *   INSTALL.C                                                             *
 *                                                                         *
 *   Copyright (C) 1992-1997 Galacticomm, Inc.    All Rights Reserved.     *
 *                                                                         *
 *   This is the generic installation utility for copying ZIP files from   *
 *   floppy to hard disk and unzipping them.  MSG files are automatically  *
 *   "updatm'd" in place in the target directory.  DOC files are not       *
 *   overwritten, on the theory that the Sysop may have changed them to    *
 *   his own liking; if a DOC file update is mandatory, the developer      *
 *   should use a different name for it (and in its MDF).  If a file with  *
 *   extension RLN has been unzipped to the destination directory, it is   *
 *   displayed in a box and can be scrolled through for viewing.           *
 *                                                                         *
 *                                            - T. Stryker 4/7/92          *
 *                                                                         *
 *   Slight change to overall scheme: a developer can optionally place any *
 *   language name he desires into DISK1.DID - if the svr has the language *
 *   in question, a choice is offered to the sysop as to whether he wants  *
 *   to overwrite all current text block versions of this language, or     *
 *   only those text blocks which don't already have verions of that       *
 *   language.  If the language is a /RIP language, and the sysop chooses  *
 *   to update only new, an extra warning message is displayed, to inform  *
 *   the sysop that he could cause confusing displays on his svr by mixing *
 *   old and new.  If no language is in DISK1.DID, INSTALL procedes as     *
 *   normal.  (This scheme is meant mainly for /RIP languages.)            *
 *                                                                         *
 *                                             - Bill Hyatt 12/11/93       *
 *                                                                         *
 ***************************************************************************/

#include "gcomm.h"
#include "errno.h"
#include "majorbbs.h"
#include "direct.h"
#include "process.h"
#include "updutl.h"
#include "excphand.h"

#define FILREV "$Revision: 34 $"

#define DIRLEN    44               /* length of directory entry windows    */
#define NSCNS      7               /* number of screens in scntbl[]        */
#define MAXINZ   800               /* maximum number of files in one ZIP   */
#define ZWEIGHT    5               /* ZIP file "weight" toward 100% done   */
#define RUNSIZ     6               /* maximum length of runbbs parameter   */
#define YNOSIZ     4               /* maximum length of yes/no string      */
#define SUPOUT "-#"                /* PKUNZIP: supress screen output       */
#define MJRCFG "WGSERV.CFG"        /* config file to look for lang in      */
#define CHDIR      1               /* performing a chdir() call            */
#define RENAME     2               /* performing a rename() call           */
#define ERRSIZ    50               /* maximum length of error message      */
#define SPECFD     1               /* BBSV6 was specified as target path   */
#define FOUND      2               /* BBSV6 found, not specified           */

#define UNZIP       0
#define UNZIPDEL    1
#define UPDMSG      2
#define UPDMSGRN    3
#define UPDMDF      4
#define RENAMF      5
#define OKASIS      6

#define RNAMFIL "RENAME.LST"       /* standard name for "rename list" file */

extern char scntbl[][GVIDSCNSIZ];  /* table of screen files from MAKESCNS  */

#define NF2KEEP    5               /* # of files to keep (not overwrite)   */

char *f2keep[NF2KEEP]={            /* list of files to keep (not overwrite)*/
     "GALAIC.TXT",
     "GALGIC.TXT",
     "GALSIC.TXT",
     "WGMCMP.BAT",
     "WGMCMT.TXT"
};

struct rnlstent {
     CHAR prvnam[GCMAXFNM];
     CHAR curnam[GCMAXFNM];
} *rnlst=NULL;

INT exicod;                        /* errorlevel returned to DOS           */
CHAR *savscn;                      /* temporary area for saving screen img */
CHAR srcspc[GCMAXPTH],*ssptr;      /* source file spec and path-end ptr    */
CHAR dstspc[GCMAXPTH],*dsptr;      /* dest file spec and path-end ptr      */
FILE *idfp;                        /* file-id FILE ptr (DISK?.DID files)   */
INT ndisks,nzips,nfiles;           /* number of disks, ZIPs, and net files */
CHAR **finzip;                     /* dyn array of file names in ZIP file  */
CHAR **zipnams;                    /* dynamic array of ZIP file names      */
INT zipno;                         /* current ZIP index we're working with */
CHAR rlnnam[GCMAXPTH];             /* RLN file name to display if any      */
CHAR lng2ow[LNGSIZ];               /* for merge1(), language to overwrite  */
CHAR runbbs[RUNSIZ];               /* DISK1.DID option to run BBS afterwd. */
CHAR chckrn[RUNSIZ];               /* for chk4rn(), for renaming svr dir   */
INT typebbs=1;                     /* type "WG^M" after install (0=NOBBS)  */
INT sch4bbs;                       /* should we search for old bbsv6?      */
CHAR dstdrv[MAXDRIVE];             /* destination drive letter             */
CHAR *savimg;                      /* Screen image save area for ck4ren()  */
CHAR *svimg2;                      /* Screen image save area for ck4ren()  */
INT n2renam=0;                     /* # of files to rename to new names    */

/* INSTALL.C 01/12/93 20.14.02 */
VOID getrnmfiles(VOID);
VOID chk4prvnam(CHAR *curnam,CHAR *prevnam);
VOID mkirec (VOID);
INT haslng (CHAR *lngnam);
INT updchc (CHAR *lngnam);
INT okasis (CHAR *fname);
INT inzipn (CHAR *str);
VOID rptprg (CHAR *stg, INT ct);
VOID dwpath (CHAR *spc);
VOID opndsk (INT n, INT force);
GBOOL isfspc (INT c, char *stg);
VOID goaway (INT xcode);
VOID simkeys (CHAR *stg);
INT fnlen (CHAR *spec);
INT opnzip (CHAR *fspc);
CHAR *nxtzfn (VOID);
VOID pupnotes (VOID);
CHAR *getline (FILE *fp, INT infile);
VOID ck4ren(INT inold);
CHAR *geterr(INT op);
GBOOL valdir(INT c);
VOID alczip(VOID);
VOID frezip(VOID);
VOID insfin(VOID);
VOID actcode(VOID);

CHAR *amsg=NULL,*aopt=NULL,*acod=NULL;  /* auto-activation code stuff */

GBOOL asksrc=FALSE; // let's just never ask this again

VOID
main(
INT argc,
CHAR *argv[])
{
TRY
     CHAR srcdrv[MAXDRIVE],srcdir[GCMAXPTH];
     static CHAR prevnam[GCMAXFNM],pnam[GCMAXFNM],mdffil[GCMAXFNM],
          dmdfil[GCMAXFNM],pmdffil[GCMAXFNM],pdmdfil[GCMAXFNM],
          fname[GCMAXFILE+1],fnamext[GCMAXFNM],onam[GCMAXFNM];
     INT i,nread;
     ULONG dspace,nspace;
     CHAR *zn;
     struct ffblk fb,mcvfb;
     INT diskno,fileno,fninzp;
     CHAR *extptr;
     CHAR *oldnam,                 /* .TTT filename for old .MSG files     */
          newnam[30];              /* uniqfn for use while merging .MSG's  */
     INT pkrc;                     /* return code from spawn of PKUNZIP    */
     static CHAR oldmdf[GCMAXPTH];
     INT ovrwrt=0;                 /* overwrite lang spec in DISK1.DID?    */
     GBOOL fndprev,fndcur;
     INT action;

     initvid();
     if ((exicod=setjmp(disaster)) != 0) {
          goaway(exicod);
     }
     setcrit();
     savscn=alcmem(GVIDSCNSIZ);
     savimg=alcmem(GVIDSCNSIZ);
     svimg2=alcmem(GVIDSCNSIZ);
     alczip();
     switch (argc) {
     case 4:
          amsg=alcdup(argv[1]);
          aopt=alcdup(argv[2]);
          acod=alcdup(argv[3]);
          asksrc=FALSE;
          typebbs=0;
          break;
     default:
     case 2:
          if (sameas(argv[1],"NOBBS")) {
               typebbs=0;
          }
          else {
               color=0;
          }
     case 1:
          break;
     }
     fnsplit(argv[0],srcdrv,srcdir,NULL,NULL);
     strcpy(srcspc,srcdrv);
     strcat(srcspc,srcdir);
     strupr(srcspc);
     srcspc[min(DIRLEN,strlen(srcspc)-1)]='\0';
     imonorcol();
     for (i=0 ; i < NSCNS ; i++) {
          cvtscn(scntbl[i]);
     }
     rlnnam[0]='\0';
     mem2scn(scntbl[0],0,GVIDSCNSIZ);
     explodeto(scntbl[2],0,0,59,3,(80-61)/2,1);
     explodeto(scntbl[1],34,1,79,3,34/2,15);
     if (asksrc) {
          explodeto(scntbl[1],0,7,47,10,2,7);
          proff(2,7);
          if (!edtval(2,2,DIRLEN+1,srcspc,isfspc,ALLCAPS+USEPOFF)) {
               goaway(1);
          }
     }
     dwpath(srcspc);
     ssptr=srcspc+strlen(srcspc);
     if (isfile(spr("%sNT.FLG",srcdrv))) {
          strcpy(dstspc,"C:\\WGSERVNT");
     }
     else if (isfile(spr("%sWGDEV.FLG",srcdrv))) {
          strcpy(dstspc,"C:\\WGDEV");
     }
     else if (isfile(spr("%sWGMAN.FLG",srcdrv))) {
          strcpy(dstspc,"C:\\WGMAN");
     }
     else {
          strcpy(dstspc,"C:\\WGSERV");
     }
     explodeto(scntbl[1],0,11,47,14,15,8);
     setatr(0x4f);
     printfat(31,2,BBSVERSTG);
     while (1) {
          proff(15,8);
          if (!edtval(2,2,DIRLEN+1,dstspc,isfspc,ALLCAPS+USEPOFF)) {
               goaway(1);
          }
          fnsplit(dstspc,dstdrv,NULL,NULL,NULL);
          if (samend(dstspc,"\\BBSV6")) {
               sch4bbs=SPECFD;
          }
          else if (isdir(spr("%s\\BBSV6",dstdrv))) {
               sch4bbs=FOUND;
          }
          else {
               sch4bbs=0;
          }
          dwpath(dstspc);
          dsptr=dstspc+strlen(dstspc);
          if (*(dsptr-1) == '\\') {
               *--dsptr='\0';
          }
          if (dstspc[1] != ':' || _chdrive(dstspc[0]-'A'+1) != 0) {
               printf("\7");
               continue;
          }
          if (strlen(dstspc) > 2 && chdir(dstspc) != 0) {
               if (mkdir(dstspc) != 0 || chdir(dstspc) != 0) {
                    printf("\7");
                    continue;
               }
          }
          mem2scn(scntbl[0]+gvscnoff(0,15),gvscnoff(0,15),4*160);
          opndsk(1,0);
          while (1) {
               lng2ow[0]='\0';
               nread=fscanf(idfp,"%d %d %ld %s %s %s",
                            &ndisks,&nfiles,&nspace,lng2ow,runbbs,chckrn);
               fclose(idfp);
               nzips=ndisks;
               if (nread > 3 || nread < 7) {
                    break;
               }
               printf("\7");
               opndsk(1,1);
          }
          switch (nread) {
          case 4:
               if (sameas(lng2ow,"CHECK")) {
                    if (sch4bbs > 0) {
                         ck4ren(sch4bbs);
                    }
               }
               break;
          case 5:
               if (sameas(runbbs,"CHECK")) {
                    if (sch4bbs > 0) {
                         ck4ren(sch4bbs);
                    }
               }
               break;
          case 6:
               if (sameas(chckrn,"CHECK")) {
                    if (sch4bbs > 0) {
                         ck4ren(sch4bbs);
                    }
               }
               break;
          }
          free(savimg);
          free(svimg2);
          nspace-=((nspace+1023L)%1024L);
          if ((dspace=dskfre(dstspc)) < nspace/1024L) {
               cursiz(GVIDNOCURS);
               scn2mem(savscn,0,GVIDSCNSIZ);
               explodeto(scntbl[1],0,15,49,24,(80-50)/2,13);
               setatr(0x4F);
               prat(3,3,"%s bytes are needed, but only %s",
                  l2as(nspace),l2as(dspace*1024L));
               if (getchc() == ESC) {
                    goaway(1);
               }
               mem2scn(savscn,0,GVIDSCNSIZ);
               strcpy(dstspc,"");
          }
          else {
               break;
          }
          cursiz(GVIDLILCURS);
          explodeto(scntbl[1],34,1,79,3,34/2,15);
     }
     if (strlen(lng2ow) > 0 && haslng(lng2ow)) {
          ovrwrt=updchc(lng2ow);
     }
     explodeto(scntbl[1],48,7,79,14,48/2,15);
     zipnams=(CHAR **)alcmem(nzips*sizeof(CHAR *));
     zipno=diskno=0;
     getrnmfiles();

     while (++diskno <= ndisks) {
          strcpy(ssptr,"pkunzip.exe");
          if (isfile(srcspc)) {
               cpyutl(srcspc,"pkunzip.exe",FOPRB,FOPWB);
          }
          strcpy(ssptr,"*.zip");
          if (fnd1st(&fb,srcspc,0)) {
               do {
                    if (diskno == 1 || !inzipn(fb.ff_name)) {
                         if (zipno >= nzips) {
                              zipnams=(CHAR **)alcrsz(zipnams,
                                                      nzips*sizeof(CHAR *),
                                                      (nzips+1)*sizeof(CHAR *));
                              nzips++;
                         }
                         rptprg(spr("Copying %s",fb.ff_name),zipno);
                         zipnams[zipno++]=alcdup(fb.ff_name);
                         strcpy(ssptr,fb.ff_name);
                         cpyutl(srcspc,fb.ff_name,FOPRB,FOPWB);
                    }
               } while (fndnxt(&fb));
          }
          if (diskno < ndisks) {
               opndsk(diskno+1,0);
               fclose(idfp);
          }
     }
     nzips=zipno;
     for (zipno=fileno=0 ; zipno < nzips ; zipno++) {
          if (!opnzip(zipnams[zipno])) {
               catastro("INVALID ZIP FILE: %s",zipnams[zipno]);
          }
          for (fninzp=0 ; (zn=nxtzfn()) != NULL ; fninzp++) {
               if (fninzp >= MAXINZ) {
                    catastro("TOO MANY FILES IN %s",zipnams[zipno]);
               }
               stzcpy(finzip[fninzp],zn,MAXPATH);
          }
          for (i=0 ; i < fninzp ; i++) {
               if (++fileno > nfiles) {
                    nfiles=fileno;
               }
               extptr=finzip[i]+strlen(finzip[i])-4;
               fileparts(GCPART_FILE,finzip[i],fname,GCMAXFILE+1);
               fileparts(GCPART_FNAM,finzip[i],fnamext,GCMAXFNM);
               action=UNZIP;
               if (sameas(extptr,".MSG")) {
                    chk4prvnam(finzip[i],prevnam);
                    if (prevnam[0] == '\0') {
                         if (isfile(finzip[i])) {
                              oldnam=spr("%.*s.TTT",fnlen(finzip[i]),finzip[i]);
                              action=UPDMSG;
                         }
                    }
                    else {
                         fndprev=isfile(prevnam);
                         fndcur=isfile(finzip[i]);
                         if (fndprev && fndcur) {
                              unlink(prevnam);
                              oldnam=spr("%.*s.TTT",fnlen(finzip[i]),finzip[i]);
                              action=UPDMSG;
                         }
                         else if (fndcur) {
                              oldnam=spr("%.*s.TTT",fnlen(finzip[i]),finzip[i]);
                              action=UPDMSG;
                         }
                         else if (fndprev) {
                              oldnam=spr("%s",prevnam);
                              action=UPDMSGRN;
                         }
                    }
               }
               else if (sameas(extptr,".MDF") || sameas(extptr,".DMD")) {
                    sprintf(mdffil,"%s.MDF",fname);
                    chk4prvnam(mdffil,prevnam);
                    if (prevnam[0] == '\0') {
                         sprintf(dmdfil,"%s.DMD",fname);
                         if (isfile(mdffil)) {
                              strcpy(oldmdf,spr("%s.MDF",fname));
                              action=UPDMDF;
                         }
                         else if (isfile(dmdfil)) {
                              strcpy(oldmdf,spr("%s.DMD",fname));
                              action=UPDMDF;
                         }
                    }
                    else {
                         fileparts(GCPART_FILE,prevnam,pnam,GCMAXFILE+1);
                         sprintf(pmdffil,"%s.MDF",pnam);
                         sprintf(pdmdfil,"%s.DMD",pnam);
                         fndprev=(isfile(pmdffil)
                               || isfile(pdmdfil));
                         sprintf(mdffil,"%s.MDF",fname);
                         sprintf(dmdfil,"%s.DMD",fname);
                         fndcur=(isfile(mdffil) || isfile(dmdfil));
                         if (fndprev && fndcur) {
                              unlink(pmdffil);
                              unlink(pdmdfil);
                              if (isfile(mdffil)) {
                                   strcpy(oldmdf,spr("%s.MDF",fname));
                              }
                              else {
                                   strcpy(oldmdf,spr("%s.DMD",fname));
                              }
                              action=UPDMDF;
                         }
                         else if (fndcur) {
                              if (isfile(mdffil)) {
                                   strcpy(oldmdf,spr("%s.MDF",fname));
                              }
                              else {
                                   strcpy(oldmdf,spr("%s.DMD",fname));
                              }
                              action=UPDMDF;
                         }
                         else if (fndprev) {
                              if (isfile(pmdffil)) {
                                   strcpy(oldmdf,spr("%s.MDF",pnam));
                              }
                              else {
                                   strcpy(oldmdf,spr("%s.DMD",pnam));
                              }
                              action=UPDMDF;
                         }
                    }
               }
               else if (sameas(extptr,".DOC") || sameas(extptr,".CFG")
                     || sameas(extptr,".REF") || sameas(extptr,".DAT")) {
                    chk4prvnam(finzip[i],prevnam);
                    if (prevnam[0] != '\0' && isfile(prevnam)) {
                         action=RENAMF;
                    }
               }
               else {
                    chk4prvnam(finzip[i],prevnam);
                    if (prevnam[0] != '\0') {
                         action=UNZIPDEL;
                    }
                    else if (okasis(finzip[i])) {
                         action=OKASIS;
                    }
               }
               switch (action) {
               case UNZIP:
                    if (sameas(extptr,".RLN") && (rlnnam[0] == '\0'
                     || sameas(finzip[i],"WGSMAIN.RLN"))) {
                         strcpy(rlnnam,finzip[i]);
                    }
                    if (sameas(finzip[i],"WGSMSX.EXE")
                     && fndfile(&fb,finzip[i],FA_RDONLY)) {
                         chmod(finzip[i],0x0180);
                    }         /* (to overwrite read-only DCNET WGSMSX)*/
               case UNZIPDEL:
                    rptprg(spr("Unzipping %s",fnmcse(fnamext)),nzips+fileno);
                    if ((pkrc=spawnl(P_WAIT,"pkunzip.exe","",SUPOUT,"-o","-d",
                                     zipnams[zipno],finzip[i],NULL)) != 0) {
                         catastro(spr("An error was encountered unzipping %s:\n"
                                      "PKUNZIP error number: %d",finzip[i],
                                      pkrc));
                    }
                    if (action == UNZIPDEL) {
                         unlink(prevnam);
                    }
                    break;
               case UPDMSG:
                    rptprg(spr("Updating %s",fnmcse(fnamext)),nzips+fileno);
                    rename(finzip[i],oldnam);
                    if ((pkrc=spawnl(P_WAIT,"pkunzip.exe","",SUPOUT,"-o","-d",
                                     zipnams[zipno],finzip[i],NULL)) != 0) {
                         catastro(spr("An error was encountered updating %s:\n"
                                      "PKUNZIP error number: %d",finzip[i],
                                      pkrc));
                    }
                    strcpy(newnam,"nmsg*.new");
                    rename(finzip[i],uniqfn(newnam));
                    merge1(oldnam,newnam,finzip[i],ovrwrt ? lng2ow : NULL);
                    freeupdm();
                    unlink(newnam);
                    unlink(oldnam);
                    break;
               case UPDMSGRN:
                    rptprg(spr("Updating %s",fnmcse(fnamext)),nzips+fileno);
                    fileparts(GCPART_FILE,oldnam,onam,GCMAXFNM);
                    strcat(onam,".TTT");
                    rename(oldnam,onam);
                    if ((pkrc=spawnl(P_WAIT,"pkunzip.exe","",SUPOUT,"-o","-d",
                                     zipnams[zipno],finzip[i],NULL)) != 0) {
                         catastro(spr("An error was encountered updating %s:\n"
                                      "PKUNZIP error number: %d",finzip[i],
                                      pkrc));
                    }
                    strcpy(newnam,"nmsg*.new");
                    rename(finzip[i],uniqfn(newnam));
                    merge1(onam,newnam,finzip[i],ovrwrt ? lng2ow : NULL);
                    freeupdm();
                    unlink(newnam);
                    unlink(oldnam);
                    break;
               case UPDMDF:
                    rptprg(spr("Updating %s",fnmcse(fnamext)),nzips+fileno);
                    strcpy(onam,"nmdf*.old");
                    rename(oldmdf,uniqfn(onam));
                    if ((pkrc=spawnl(P_WAIT,"pkunzip.exe","",SUPOUT,"-o","-d",
                                     zipnams[zipno],finzip[i],NULL)) != 0) {
                         catastro(spr("An error was encountered updating %s:\n"
                                      "PKUNZIP error number: %d",finzip[i],
                                      pkrc));
                    }
                    strcpy(newnam,"nmdf*.new");
                    rename(finzip[i],uniqfn(newnam));
                    updmdf(TRUE,onam,newnam,finzip[i]);
                    //  This keeps modules disabled if they were disabled.
                    if (samend(oldmdf,".DMD") && samend(finzip[i],".MDF")) {
                         if (strlen(finzip[i]) > strlen(".DMD")) {
                              strcpy(newnam,finzip[i]);
                              strcpy(&newnam[strlen(newnam)-strlen(".DMD")],".DMD");
                              rename(finzip[i],newnam);
                         }
                    }
                    break;
               case RENAMF:
                    rptprg(spr("Updating %s",fnmcse(fnamext)),nzips+fileno);
                    rename(prevnam,fnamext);
                    break;
               case OKASIS:
                    rptprg(spr("%s ok as is",fnmcse(fnamext)),nzips+fileno);
               }
          }
     }
     if (amsg != NULL) {
          actcode();
     }
     unlink("wgsint.ref");
     unlink("wgsintcs.ref");
     unlink("wgsmdf.ref");
     unlink("bbs.bat");
     rename("mjrbbs.cfg","wgserv.cfg");
     pupnotes();
     frezip();
     if (fndfile(&fb,"wgsmajor.msg",0)
         && (!fndfile(&mcvfb,"wgsmajor.mcv",0)
             || mcvfb.ff_ftime != fb.ff_ftime
             || mcvfb.ff_fdate != fb.ff_fdate)) {
          unlink("wgsmajor.mcv");
          if (spawnl(P_WAIT,"WGSMSX.EXE","wgsmajor",NULL) == -1) {
               catastro("Error generating WGSMAJOR.MCV!");
          }
     }
     mkirec();
     if (typebbs) {
          switch (nread) {
          case 4:
               if (!sameas(lng2ow,"NOBBS")) {
                    simkeys("WG\r");
               }
               else {
                    insfin();
               }
               break;
          case 5:
          case 6:
               if (!sameas(runbbs,"NOBBS")) {
                    simkeys("WG\r");
               }
               else {
                    insfin();
               }
               break;
          default:
               simkeys("WG\r");
               break;
          }
     }
     else {
          insfin();
     }
     locate(0,24);
     cursiz(GVIDLILCURS);
     goaway(0);
EXCEPT
}

VOID
getrnmfiles(VOID)
{
     FILE *rnfptr;
     CHAR rnbuf[80],specbuf[GCMAXPTH],*cp;

     fileparts(GCPART_PATH,srcspc,specbuf,GCMAXPTH);
     if ((rnfptr=fopen(spr("%s\\%s",specbuf,RNAMFIL),FOPRA)) != NULL) {
          while (fgets(rnbuf,80,rnfptr) != NULL) {
               n2renam++;
          }
          if (n2renam > 0) {
               rewind(rnfptr);
               rnlst=(struct rnlstent *)alczer(n2renam*sizeof(struct rnlstent));
               n2renam=0;
               while (fgets(rnbuf,80,rnfptr) != NULL) {
                    if (*(cp=rnbuf+strlen(rnbuf)-1) == '\n') {
                         *cp='\0';
                    }
                    stlcpy(rnlst[n2renam].prvnam,itemidxd(rnbuf,0,","),
                           GCMAXFNM);
                    stlcpy(rnlst[n2renam].curnam,itemidxd(rnbuf,1,","),
                           GCMAXFNM);
                    n2renam++;
               }
          }
          fclose(rnfptr);
     }
}

VOID
chk4prvnam(
CHAR *curnam,
CHAR *prevnam)
{
     INT i;

     prevnam[0]='\0';
     for (i=0 ; i < n2renam ; i++) {
          if (sameas(curnam,rnlst[i].curnam)) {
               stlcpy(prevnam,rnlst[i].prvnam,GCMAXFNM);
               return;
          }
     }
}

VOID
mkirec(VOID)                       /* make GALIREC.TXT, record of install  */
{                                  /* source & destination paths           */
     FILE *fp;

     *ssptr='\0';
     *dsptr='\0';
     if ((fp=fopen("GALIREC.TXT",FOPWA)) != NULL) {
          fprintf(fp,"%s\n%s\n",srcspc,dstspc);
          fclose(fp);
     }
}

INT
haslng (                           /* see if WGSERV.CFG has spec lang      */
CHAR *lngnam)                      /*      language to check on            */
{
     if (tfsopn(MJRCFG) > 0) {
          while (tfsrdl() != TFSDUN) {
               if (tfstate == TFSLIN) {
                    if (tfspfx("LNG=") && sameto(lngnam,tfspst)) {
                         tfsabt();
                         return(1);
                    }
               }
          }
     }
     return(0);
}

INT
updchc(                            /* does user want to ovrwrt a language? */
CHAR *lngnam)                      /*      language to check on            */
{
     CHAR ynbuf[3+1];
     INT choice,lenp1;
     static CHAR *updchcs[2],savscn[GVIDSCNSIZ],svscn2[GVIDSCNSIZ];

     updchcs[0]=alcmem(100);
     updchcs[1]=alcmem(100);
     sprintf(updchcs[0]," UPDATE ALL - update all %s text blocks ",lngnam);
     sprintf(updchcs[1]," UPDATE NEW - update new %s text blocks only ",lngnam);
     mem2scn(savscn,0,GVIDSCNSIZ);
     explodeto(scntbl[2],0,4,63,24,7,2);
     lenp1=strlen(lngnam)+1;
     setatr(0x3F);
     proff(0,0);
     prat(23,5,"%s text blocks?",lngnam);
     prat(9,8,"%s text blocks with the latest versions",lngnam);
     prat(54,12,"%s",lngnam);
     prat(53,14,"%s",lngnam);
     nslatr=0x3F;
     while (1) {
          choice=choose(2,updchcs,11,19,66,20,1);
          if (choice == -ESC) {
               goaway(1);
          }
          if (!samend(lngnam,RIPSFX) || choice == 0) {
               mem2scn(savscn,0,GVIDSCNSIZ);
               if (updchcs[0] != NULL) {
                    free(updchcs[0]);
                    free(updchcs[1]);
                    updchcs[0]=NULL;
                    updchcs[1]=NULL;
               }
               return(choice == 0);
          }
          mem2scn(svscn2,0,GVIDSCNSIZ);
          explode(scntbl[3],0,0,79,24);
          proff(0,0);
          setatr(0x1E);
          prat(33,4,"%s",lngnam);
          setatr(0x1F);
          prat(33+lenp1,4,"is a RIP language, by",lngnam);
          setatr(0x1E);
          prat(60,5,"%s",lngnam);
          prat(53,16,"%s",lngnam);
          setatr(0x1F);
          prat(53+lenp1,16,"text");
          setatr(0x1E);
          prat(18,21,"%s",lngnam);
          setatr(0x1F);
          prat(18+lenp1,21,"text blocks included with this version?");
          strcpy(ynbuf,"No ");
          if (!edtval(59+strlen(lngnam),21,4,ynbuf,validyn,MCHOICE)
              || ynbuf[0] == 'N') {
               mem2scn(svscn2,0,GVIDSCNSIZ);
          }
          else {
               mem2scn(savscn,0,GVIDSCNSIZ);
               if (updchcs[0] != NULL) {
                    free(updchcs[0]);
                    free(updchcs[1]);
                    updchcs[0]=NULL;
                    updchcs[1]=NULL;
               }
               return(0);
          }
     }
}

INT
okasis(                            /* is this file ok as it is right now?  */
CHAR *fname)                            /* file name to check              */
{
     INT oksofar,i;
     CHAR basenam[GCMAXFNM+1],fpath[GCMAXPTH],*fnptr;

     oksofar=0;
     fnptr=fname;
     if (samend(fname,".DOC")) {
          oksofar=1;
     }
     else if (samend(fname,".CVT")) {
          if (isfile(fname)) {
               oksofar=1;
          }
          else {
               fileparts(GCPART_PATH,fname,fpath,sizeof(fpath));
               if (samend(fpath,"/")) {
                    fpath[strlen(fpath)-1]='\0';
               }
               fileparts(GCPART_FILE,fname,basenam,sizeof(basenam));
               if (samend(dstspc,SLS)) {
                    fnptr=spr("%s%s"SLS"%s.CV_",dstspc,fpath,basenam);
               }
               else {
                    fnptr=spr("%s"SLS"%s"SLS"%s.CV_",dstspc,fpath,basenam);
               }
               if (isfile(fnptr)) {
                    oksofar=1;
               }
          }
     }
     else if (sameas(fname,"GALGSBL.DLL")) {
          if (isfile("GALNEWG.SBL")) {
               oksofar=1;
          }
     }
     else {
          for (i=0 ; i < NF2KEEP ; i++) {
               if (sameas(fname,f2keep[i])) {
                    oksofar=1;
                    break;
               }
          }
     }
     return(oksofar ? isfile(fnptr) : 0);
}

INT
inzipn(                            /* is str in the ZIP name list already? */
CHAR *str)                              /* candidate new ZIP name to look 4*/
{
     INT i;

     for (i=0 ; i < zipno ; i++) {
          if (strcmp(zipnams[i],str) == 0) {
               return(1);
          }
     }
     return(0);
}

VOID
rptprg(                            /* report progress w/moving bar and %   */
CHAR *stg,
INT ct)
{
     INT i,nblips;
     UINT totwgt,pctdun;

     cursiz(GVIDNOCURS);
     proff(48/2,15);
     setatr(0x1F);
     prat(3,2,"%-26s",spr("%s...",stg));
     if (ct <= nzips) {
          ct*=ZWEIGHT;
     }
     else {
          ct=nzips*ZWEIGHT+(ct-nzips);
     }
     totwgt=nzips*ZWEIGHT+nfiles;
     if ((pctdun=(ct*100+totwgt/2)/totwgt) < 1) {
          pctdun=1;
     }
     prat(11,6,"%3u",pctdun);
     nblips=(ct*48+totwgt/2)/totwgt;
     setatr(0x1A);
     prat(4,5,"");
     for (i=0 ; i < nblips/2 ; i++) {
          printf("Û");
     }
     if (nblips&1) {
          printf("Ý");
     }
}

VOID
dwpath(                            /* deal with entered path string        */
CHAR *spc)
{
     INT len,c;

     if ((len=strlen(spc)) == 0) {
          getcwd(spc,GCMAXPTH);
     }
     if ((c=spc[len-1]) != ':' && c != '\\') {
          strcat(spc,"\\");
     }
}

VOID
opndsk(                            /* open (ensure in drive) diskette #n   */
INT n,                             /*    force=1 means force "insert" box  */
INT force)
{
     cursiz(GVIDNOCURS);
     sprintf(ssptr,"disk%d.did",n);
     while (force || (idfp=fopen(srcspc,FOPRA)) == NULL) {
          force=0;
          scn2mem(savscn,0,GVIDSCNSIZ);
          explodeto(scntbl[1],0,0,31,6,19,13);
          setatr(0x3F);
          prat(25,1,"%d",n);
          prat(19,2,"%c",srcspc[0]);
          if (getchc() == ESC) {
               goaway(1);
          }
          mem2scn(savscn,0,GVIDSCNSIZ);
     }
}

GBOOL
isfspc(                            /* returns 1 if char is valid filespec  */
INT c,
CHAR *stg)
{
     return(isfiln(c,stg) || c == ':' || c == '\\');
}

VOID
goaway(                            /* call it quits                        */
INT xcode)
{
     locate(0,24);
     cursiz(GVIDLILCURS);
     setatr(0x07);
     printf("\r");
     exit(xcode);
}

VOID
simkeys(                           /* simulate keys to BIOS kbd inp buffer */
CHAR *stg)                              /* string of keystrokes to simulate*/
{
     unsigned kbstart,kbend,kbtail;

     kbstart=peek(0x0040,0x0080);
     kbend=peek(0x0040,0x0082);
     kbtail=peek(0x0040,0x001C);
     while (*stg != '\0') {
          pokeb(0x0040,kbtail++,*stg);        /* ASCII character            */
          pokeb(0x0040,kbtail++,0);           /* scan code                  */
          stg++;
          if (kbtail >= kbend) {
               kbtail=kbstart;
          }
     }
     poke(0x0040,0x001C,kbtail);
}

INT
fnlen(                             /* return file name length              */
CHAR *spec)
{
     INT slen;

     for (slen=0 ; spec[slen] != '\0' && spec[slen] != '.' ; slen++) {
     }
     return(slen);
}

/*********************** ZIP NAME READOUT SECTION **************************/
// HACK need to deal with alignment

struct filhead {                   /* 30 bytes+filename needed             */
     CHAR headr[4];                /*    Should be 0x04034B50              */
     SHORT versneed;               /*    version of pkzip needed to extract*/
     SHORT flags;                  /*    general purpose bitflags          */
     SHORT method;                 /*    compression method                */
     SHORT ftime;                  /*    file time                         */
     SHORT fdate;                  /*    file date                         */
     ULONG crc32;                  /*    file crc                          */
     LONG compsz;                  /*    compressed size                   */
     LONG normsz;                  /*    uncompressed size                 */
     SHORT namesz;                 /*    filename size                     */
     SHORT xtrasz;                 /*    extra field size                  */
} *fhdr;

struct dirhead {                   /* 46+filename                          */
     CHAR headr[4];                /*    Should be 0x02014B50              */
     SHORT versmade;               /*    version of pkzip that created     */
     SHORT versneed;               /*    version of pkzip needed to extract*/
     SHORT flags;                  /*    general purpose bitflags          */
     SHORT method;                 /*    compression method                */
     SHORT ftime;                  /*    file time                         */
     SHORT fdate;                  /*    file date                         */
     ULONG crc32;                  /*    file crc                          */
     LONG compsz;                  /*    compressed size                   */
     LONG normsz;                  /*    uncompressed size                 */
     SHORT namesz;                 /*    filename size                     */
     SHORT xtrasz;                 /*    extra field size                  */
     SHORT commsz;                 /*    file comment length               */
     SHORT dsknst;                 /*    disk number start                 */
     SHORT infatr;                 /*    internal file attributes          */
     LONG extatr;                  /*    external file attributes          */
     LONG offshd;                  /*    offset to local header            */
} *dhdr;

FILE *zipfp;                       /* zip file pointer to open ZIP file    */
LONG zippos;                       /* file position in open ZIP file       */

INT
opnzip(                            /* prepare to view a ZIP file's contents*/
CHAR *fspc)                        /*    file path specification           */
{
     CHAR linbuf[64];

     if ((zipfp=fopen(fspc,FOPRB)) != NULL) {
          if (fread(linbuf,64,1,zipfp) == 1) {
               if (linbuf[0]  == 'P'  && linbuf[1] == 'K'
                && linbuf[2]  == 0x03 && linbuf[3] == 0x04) {
                    zippos=0;
                    return(1);
               }
          }
          fclose(zipfp);
     }
     return(0);
}

CHAR *                                 /* return NULL if error or all done */
nxtzfn(VOID)                       /* View an ARC/ZIP's filenames 1 by 1   */
{
     CHAR linbuf[46];
     INT hdr;
     INT done=0;
     static CHAR zfname[GCMAXPTH];

     while (!done) {
          if (fseek(zipfp,zippos,0) != 0
           || fread(linbuf,46,1,zipfp) != 1) {
               break;
          }
          dhdr=(struct dirhead *)linbuf;
          fhdr=(struct filhead *)linbuf;
          hdr=(CHAR)fhdr->headr[2]+((CHAR)fhdr->headr[3]*256);
          switch (hdr) {
          case 0x01EF:             /* Self-Extracting Header               */
               zippos=0x31F0L;
               break;
          case 0x0201:             /* Directory record                     */
               if (fread(zfname,dhdr->namesz,1,zipfp) != 1) {
                    catastro("NXTZFN: Error reading file name!");
               }
               zfname[dhdr->namesz]='\0';
               zippos=zippos+0x2e+dhdr->namesz+dhdr->xtrasz+dhdr->commsz;
               return(zfname);
          case 0x0403:             /* File header record                   */
               zippos=zippos+0x1e+fhdr->namesz+fhdr->xtrasz+fhdr->compsz;
               break;
          case 0x0605:             /* End of Central Dir Record            */
               done=1;
               break;
          default:
               done=1;
          }
     }
     fclose(zipfp);
     return(NULL);
}

/********************* RELEASE NOTES DISPLAY SECTION ***********************/

static INT nroom=0,nposs=0;
static LONG *fposs;

VOID
pupnotes(VOID)                     /* put up release notes if any     */
{
     FILE *fp;
     CHAR *cp;
     INT i,whereat;

     if (rlnnam[0] != '\0' && (fp=fopen(rlnnam,FOPRB)) != NULL) {
          mem2scn(scntbl[4],0,GVIDSCNSIZ);
          setwin(0L,2,1,78,23,0);
          cursiz(GVIDNOCURS);
          ansion(1);
          setatr(0x1E);
          for (i=0 ; i < 23 ; i++) {
               if ((cp=getline(fp,i)) != NULL) {
                    locate(2,i+1);
                    printf("%s",cp);
                    cleareol();
               }
          }
          whereat=0;
          while (1) {
               switch (getchc()) {
               case HOME:
                    printf("\14");
                    for (i=0 ; i < 23 ; i++) {
                         if ((cp=getline(fp,i)) != NULL) {
                              locate(2,i+1);
                              printf("%s",cp);
                              cleareol();
                         }
                    }
                    whereat=0;
                    break;
               case END:
                    printf("\14");
                    getline(fp,0x7FFF);
                    whereat=(nposs-23 < 0 ? 0 : nposs-23);
                    for (i=0 ; i < 23 ; i++) {
                         if ((cp=getline(fp,whereat+i)) != NULL) {
                              locate(2,i+1);
                              printf("%s",cp);
                              cleareol();
                         }
                    }
                    break;
               case CRSRUP:
                    if ((cp=getline(fp,whereat-1)) != NULL) {
                         scn2scn(160,2*160,22*160);
                         locate(2,1);
                         printf("%s",cp);
                         cleareol();
                         whereat--;
                    }
                    break;
               case CRSRDN:
                    if ((cp=getline(fp,whereat+23)) != NULL) {
                         scn2scn(2*160,160,22*160);
                         locate(2,23);
                         printf("%s",cp);
                         cleareol();
                         whereat++;
                    }
                    break;
               case PGUP:
                    for (i=0 ; i < 22 ; i++) {
                         if ((cp=getline(fp,whereat-1)) != NULL) {
                              scn2scn(160,2*160,22*160);
                              locate(2,1);
                              printf("%s",cp);
                              cleareol();
                              whereat--;
                         }
                    }
                    break;
               case PGDN:
                    for (i=0 ; i < 22 ; i++) {
                         if ((cp=getline(fp,whereat+23)) != NULL) {
                              scn2scn(2*160,160,22*160);
                              locate(2,23);
                              printf("%s",cp);
                              cleareol();
                              whereat++;
                         }
                    }
                    break;
               case ESC:
                    fclose(fp);
                    if (nroom > 0) {
                         free(fposs);
                         nroom=nposs=0;
                    }
                    return;
               }
          }
     }
}

CHAR *
getline(
FILE *fp,
INT infile)
{
     static INT inbuf=-1;
     static LONG sofar=0L;
     static INT fpdone=0;
     static CHAR datbuf[121];
     INT len;

     if (infile >= nposs && !fpdone) {
          fseek(fp,sofar,0);
          while (infile >= nposs && !fpdone) {
               if (fgets(datbuf,sizeof(datbuf),fp) == NULL) {
                    fpdone=1;
                    inbuf=-1;
               }
               else if (datbuf[0] == ('Z'&0x1F)) {
                    nposs--;
                    fpdone=1;
                    inbuf=-1;
               }
               else {
                    if (nposs >= nroom) {
                         if (nroom == 0) {
                              nroom=100;
                              fposs=(LONG *)alcmem(nroom*sizeof(LONG));
                              fposs[0]=0L;
                              nposs=1;
                         }
                         else {
                              fposs=(LONG *)alcrsz(fposs,nroom*sizeof(LONG),
                                                   (nroom+100)*sizeof(LONG));
                              nroom+=100;
                         }
                    }
                    inbuf=nposs-1;
                    sofar=fposs[nposs++]=ftell(fp);
               }
          }
     }
     if (infile >= nposs || infile < 0) {
          return(NULL);
     }
     if (infile != inbuf) {
          fseek(fp,fposs[infile],0);
          if (fgets(datbuf,sizeof(datbuf),fp) == NULL) {
               strcpy(datbuf,"\n");
          }
          inbuf=infile;
     }
     while ((len=strlen(datbuf)) != 0) {
          switch (datbuf[len-1]) {
          case '\n':
          case '\r':
               datbuf[len-1]='\0';
               break;
          case 'Z'&0x1F:
               return(NULL);
          default:
               return(datbuf);
          }
     }
     return(datbuf);
}

VOID
ck4ren(                            /* ask if we want to rename directory   */
INT inold)                         /*   was BBSV6 specified or found?      */
{
     CHAR tmpdir[MAXFILE],spcdir[DIRLEN],yesno[YNOSIZ];
     GBOOL editng=TRUE,gotans=FALSE;
     INT keyhit;

     stzcpy(yesno,"Yes",YNOSIZ);
     stzcpy(tmpdir,"WGSERV",MAXFILE);
     stzcpy(spcdir,dstspc,DIRLEN);
     setatr(0x1F);
     scn2mem(savimg,0,GVIDSCNSIZ);
     while (editng) {
          switch (inold) {
          case SPECFD:
               if (!gotans) {
                    explodeto(scntbl[5],0,0,63,9,7,7);
                    locate(31,12);
                    printf("%s",dstdrv);
                    if (!edtval(51,7,YNOSIZ,yesno,validyn,USEPOFF+MCHOICE)) {
                         goaway(2);
                    }
               }
               if (sameas(yesno,"YES")) {
                    gotans=TRUE;
                    mem2scn(savimg,0,GVIDSCNSIZ);
                    explodeto(scntbl[5],0,20,63,24,7,9);
                    prat(41,2,"%s",dstdrv);
                    if (!edtval(44,2,MAXFILE,tmpdir,valdir,ALLCAPS+USEPOFF)) {
                         goaway(2);
                    }
               }
               else {
                    mem2scn(savimg,0,GVIDSCNSIZ);
                    return;
               }
               if (sameas(tmpdir,"BBSV6")) {
                    printf("\7");
                    scn2mem(svimg2,0,GVIDSCNSIZ);
                    explodem=0;
                    explodeto(scntbl[6],0,5,42,9,17,9);
                    do {
                    } while (getchc() != 13);
                    stzcpy(tmpdir,"WGSERV",MAXFILE);
                    mem2scn(svimg2,0,GVIDSCNSIZ);
               }
               else if (strlen(tmpdir) < 1) {
                    printf("\7");
                    scn2mem(svimg2,0,GVIDSCNSIZ);
                    explodem=0;
                    explodeto(scntbl[6],0,0,36,4,20,9);
                    do {
                    } while (getchc() != 13);
                    stzcpy(tmpdir,"WGSERV",MAXFILE);
                    mem2scn(svimg2,0,GVIDSCNSIZ);
               }
               else {
                    editng=FALSE;
               }
               break;
          case FOUND:
               if (!gotans) {
                    explodeto(scntbl[5],0,10,63,19,7,7);
                    locate(23,10);
                    printf("%s",dstdrv);
                    locate(44,12);
                    printf("%s",dstdrv);
                    if (!edtval(50,7,YNOSIZ,yesno,validyn,USEPOFF+MCHOICE)) {
                         goaway(2);
                    }
               }
               if (sameas(yesno,"YES")) {
                    gotans=TRUE;
                    mem2scn(savimg,0,GVIDSCNSIZ);
                    explodeto(scntbl[5],0,20,63,24,7,9);
                    prat(41,2,"%s",dstdrv);
                    if (!edtval(44,2,MAXFILE,tmpdir,valdir,ALLCAPS+USEPOFF)) {
                         goaway(2);
                    }
               }
               else {
                    mem2scn(savimg,0,GVIDSCNSIZ);
                    return;
               }
               if (sameas(tmpdir,"BBSV6")) {
                    printf("\7");
                    scn2mem(svimg2,0,GVIDSCNSIZ);
                    explodem=0;
                    explodeto(scntbl[6],0,5,42,9,17,9);
                    do {
                    } while (getchc() != 13);
                    stzcpy(tmpdir,"WGSERV",MAXFILE);
                    mem2scn(svimg2,0,GVIDSCNSIZ);
               }
               else if (strlen(tmpdir) < 1) {
                    printf("\7");
                    scn2mem(svimg2,0,GVIDSCNSIZ);
                    explodem=0;
                    explodeto(scntbl[6],0,0,36,4,20,9);
                    do {
                    } while (getchc() != 13);
                    stzcpy(tmpdir,"WGSERV",MAXFILE);
                    mem2scn(svimg2,0,GVIDSCNSIZ);
               }
               else {
                    editng=FALSE;
               }
               break;
          }
     }
     explodem=1;
     stzcpy(dstspc,spr("%s\\%s",dstdrv,tmpdir),DIRLEN);
     dsptr=dstspc+strlen(dstspc);
     if (*(dsptr-1) == '\\') {
          *--dsptr='\0';
     }
     if (chdir("\\") == -1) {
          catastro(spr("Error changing to root directory!\n"
                       "                  (%s)",geterr(CHDIR)));
     }
     if (rmdir(dstspc) == 0) {
          if (rename(spr("%s\\BBSV6",dstdrv),dstspc) == -1) {
               catastro(spr("Error renaming directory \"%s\"\n"
                            "                  (%s)",strupr(spcdir),
                                                     geterr(RENAME)));
          }
     }
     else {
          printf("\7");
          explodeto(scntbl[6],0,10,44,19,16,8);
          do {
               keyhit=getchc();
               if (keyhit == ESC) {
                    goaway(1);
               }
          } while (keyhit != 13);
          strcpy(dstspc,spcdir);
     }
     if (chdir(dstspc) == -1) {
          catastro(spr("Error switching to directory \"%s\"\n"
                       "                  (%s)",strupr(dstspc),
                                                geterr(CHDIR)));
     }
     mem2scn(savimg,0,GVIDSCNSIZ);
     locate(14,12);
     setatr(0x2B);
     printf("%-44.44s",dstspc);
}

CHAR *                             /*   Returns pointer to error message   */
geterr(                            /* Determines cause of error            */
INT op)                            /*   Operation in which error occured   */
{
     static char errmsg[ERRSIZ];

     switch (errno) {
     case ENOENT:
          stzcpy(errmsg,op == RENAME ? "No such file or directory"
                                     : "Path or file name not found",ERRSIZ);
          break;
     case EACCES:
          stzcpy(errmsg,"Permission denied",ERRSIZ);
          break;
     case ENOTSAM:
          stzcpy(errmsg,"Not same device",ERRSIZ);
          break;
     default:
          stzcpy(errmsg,"Unknown error",ERRSIZ);
          break;
     }
     return(errmsg);
}

GBOOL
valdir(                            /* edtval() valrou for directory name   */
INT c)
{
     return((c <= 255 && isalnum(c)) || c == '!' || c == '@' || c == '#'
          || c == '$' || c == '%' || c == '^' || c == '&' || c == '('
          || c == ')' || c == '-' || c == '_' || c == '=' || c == '+'
          || c == '[' || c == ']' || c == '{' || c == '}' || c == '.');
}

VOID
alczip(VOID)                       /* Allocate all memory for files in ZIP */
{
     UINT alcloop;

     finzip=(char **)alcmem(MAXINZ*sizeof(char *));
     for (alcloop=0 ; alcloop < MAXINZ ; alcloop++) {
          finzip[alcloop]=alcmem(MAXPATH);
     }
}

VOID
frezip(VOID)                       /* Frees zip-related allocated memory   */
{
     UINT alcloop;

     for (alcloop=0 ; alcloop < MAXINZ ; alcloop++) {
          free(finzip[alcloop]);
     }
     free(finzip);
     for (alcloop=0 ; alcloop < nzips ; alcloop++) {
          free(zipnams[alcloop]);
     }
     free(zipnams);
}

VOID
insfin(VOID)                       /* notify user that install is complete */
{
     mem2scn(scntbl[0],0,GVIDSCNSIZ);
     explodem=0;
     explodeto(scntbl[2],0,0,59,3,(80-61)/2,1);
     explodem=1;
     explodeto(scntbl[6],37,0,64,4,25,9);
     getchc();
}

VOID
actcode(VOID)
{
     setcnf(aopt,acod);
     applyem(amsg);
}
