/***************************************************************************
 *                                                                         *
 *   GALIARIP.C                                                            *
 *                                                                         *
 *   Copyright (c) 1993-1997 Galacticomm, Inc.     All Rights Reserved.    *
 *                                                                         *
 *   This is the utility to install RIP support for the add-ons.           *
 *                                                                         *
 *                                                 - Bill Hyatt 9/17/93    *
 *                                                                         *
 ***************************************************************************/

#include "gcomm.h"
#include "majorbbs.h"
#include <process.h>
#include "excphand.h"

#define FILREV "$Revision: 10 $"

/* ---- importing RIP graphics, import modes ----------------------------- */
#define IMPALL 0                   /* import all text blocks               */
#define IMPNEW 20                  /*   "    new  "     "    only          */
/* ---- for tellem(), what did sysop choose? ----------------------------- */
#define IMPAPP 100                 /* imported RIP graphics & appended mnu */
#define IMPNAP 150                 /*  "    "     "     ", didn't append   */
#define NOIMPT 200                 /* aborted RIP graphics import          */
/* ---- exit codes (code 0 for all is well) ------------------------------ */
#define NORIP  50                  /* no English/RIP found in WGSERV.CFG   */
#define NONFND 60                  /* no RIP-supported modules found       */
#define NOINST 70                  /* for one module, chose not to install */
/* ---- misc. -------------------------------------------------------------*/
#define JSTONE -1                  /* installing RIP for just one module   */
#define CFGSEP '/'                 /* sep CHAR for fil nms in GALIARIP.CFG */
#define RBFSIZ 100                 /* len of buffer for file reads         */
#define NSCNS  5                   /* number of screen files               */
#define ENTNAM "Ent. Teleconference" /* Name for Ent. Tele. in mod. list   */

extern CHAR scntbl[][GVIDSCNSIZ];/* table of pre-OBJ'd scn files   */

CHAR **modlst,                     /* list of module names w/ RIP support  */
     modnam[MNMSIZ+1],             /* module name from .MDF file           */
     mdfnam[FNMSIZ],               /* module's .MDF file name              */
     zirnam[FNMSIZ];               /* name of .ZIR archive w/ needed files */

INT savx,savy,                     /* saved cursor position                */
    scur;                          /*   "     "    size                    */

FILE *cfgfil;                      /* config file w/ needed file names     */

struct filnms {                    /* file name info block                 */
     CHAR zirnam[FNMSIZ];          /*   .ZIR archive file on add-on disk   */
     CHAR mlrnam[FNMSIZ];          /*   .MLR import file (archived)        */
     CHAR ripnam[FNMSIZ];          /*   appendable RIP scene for add-on    */
} *fillst,                         /* list of file names for mult install  */
  fnames;                          /* file names for only one              */

struct scninfo {                   /* saved screen info data block         */
     CHAR *scn;                    /*      saved screen                    */
     struct scninfo *nxtscn;       /*      next screen on stack            */
} *screens=NULL,                   /* LIFO stack of saved screens          */
  *curscn=NULL;                    /* pointer to top of screen stack       */

static VOID init(VOID);
static INT instrip(CHAR *modnam);
static VOID getall(VOID);
static VOID sortem(INT num);
static VOID gtnams(CHAR *mdfnam,CHAR *zirnam,INT i);
static INT gcfgln(CHAR *mdfnam,CHAR *zirnam);
static CHAR *gmdfinf(CHAR *mdfnam,CHAR *pfix);
static VOID irip(CHAR *modnam,struct filnms fnams);
static INT dozir(CHAR *modnam,struct filnms fnams);
static INT imprip(CHAR *modnam,struct filnms fnams);
static INT appmnu(CHAR *modnam,struct filnms fnams);
static VOID tellem(INT whtdid,CHAR *modnam,struct filnms fnams);
static INT filxst(CHAR *filnam);
static VOID pushscn(VOID);
static VOID popscn(VOID);
static VOID pat(INT x,INT y,CHAR *pstg,INT atr,INT csiz);
static VOID updcfg(CHAR *mdfnam,CHAR *zirnam);
static INT xit(INT xitcod);

INT
main(argc,argv)                    /* main program entry point             */
INT argc;
CHAR *argv[];
{
TRY
     INT i;

#ifdef GCWINNT
     if (!canRunUtil()) {
          MessageBox(NULL,NOPROCEED,
                    argv[0],MB_ICONSTOP|MB_OK|MB_TASKMODAL|MB_SETFOREGROUND);
          return(1);
     }
#endif // GCWINNT
     initvid();
     init();
     if (argc < 3) {
          if ((cfgfil=fopen("GALIARIP.CFG",FOPRA)) == NULL) {
               catastro("Unable to open GALIARIP.CFG!");
          }
          getall();
          i=0;
          while ((i=choowd(modlst,i,27,6,51,16,TRUE)) != -ESC) {
               irip(modlst[i],fillst[i]);
          }
          fclose(cfgfil);
     }
     else {
          strcpy(mdfnam,argv[1]);
          strcpy(zirnam,argv[2]);
          gtnams(mdfnam,zirnam,JSTONE);
          if (!instrip(modnam)) {
               return(xit(NOINST));
          }
          irip(modnam,fnames);
     }
     return(xit(0));
EXCEPT
#ifdef GCWINNT
     return(1);
#endif // GCWINNT
}

static VOID
init(VOID)                         /* see if svr has RIP, set things up    */
{
     INT i,fndrip=0;

     if (tfsopn("WGSERV.CFG") == 0) {
          catastro("INIT: WGSERV.CFG not found!");
     }
     while (tfsrdl() != TFSDUN) {
          if (tfstate == TFSLIN && !fndrip) {
               fndrip=(tfspfx("LNG=") && sameas(tfspst,"English/RIP"));
          }
     }
     if (!fndrip) {
          exit(xit(NORIP));
     }
     savx=curcurx();
     savy=curcury();
     scur=curcurs();
     selatr=0x70;
     nslatr=0x2E;
     setcrit();
     for (i=0 ; i < NSCNS ; i++) {
          cvtscn(scntbl[i]);
     }
}

static INT                         /* see if user wants to install RIP     */
instrip (modnam)                   /* support for one module               */
CHAR *modnam;                      /*     name of module in question       */
{
     CHAR *ynbuf="Yes";

     pushscn();
     explodeto(scntbl[4],0,0,46,9,17,7);
     pat(19,8,spr("%s ",modnam),0x3E,GVIDNOCURS);
     setatr(0x3F);
     printf("also comes with");
     if (!edtval(49,15,4,ynbuf,validyn,MCHOICE)) {
          return(0);
     }
     return(ynbuf[0] == 'Y');
}

static VOID
getall(VOID)                       /* search for add-on .mdf files, get    */
{                                  /*    needed file names, set up things  */
     register INT i=0;

     while (gcfgln(mdfnam,zirnam)) {
          if (filxst(mdfnam)) {
               i++;
          }
     }
     if (i == 0) {
          pushscn();
          explodeto(scntbl[1],0,0,50,10,14,6);
          getchc();
          exit(xit(NONFND));
     }
     rewind(cfgfil);
     fillst=(struct filnms *)alczer(i*sizeof(struct filnms));
     modlst=(CHAR **)alczer((i+1)*sizeof(CHAR **));
     i=0;
     while (gcfgln(mdfnam,zirnam)) {
          if (filxst(mdfnam)) {
               gtnams(mdfnam,zirnam,i);
               i++;
          }
     }
     modlst[i+1]=NULL;
     sortem(i);
     pushscn();
     explode(scntbl[0],9,0,70,24);
     proff(0,0);
}

static VOID
sortem(num)                        /* sort module name & file name lists   */
INT num;                           /*    number of modules to sort         */
{
     CHAR *hldstg;
     INT mid,i,j;
     struct filnms hldnms;

     for (mid=num/2 ; mid > 0 ; mid=mid/2) {
          for (i=mid ; i < num ; i++) {
               for (j=i-mid ; j >= 0 ; j -=mid) {
                    if (strcmp(modlst[j],modlst[j+mid]) <= 0) {
                         break;
                    }
                    hldstg=modlst[j];
                    modlst[j]=modlst[j+mid];
                    modlst[j+mid]=hldstg;
                    movmem((CHAR *)&fillst[j],(CHAR *)&hldnms,
                           sizeof(struct filnms));
                    movmem((CHAR *)&fillst[j+mid],(CHAR *)&fillst[j],
                           sizeof(struct filnms));
                    movmem((CHAR *)&hldnms,(CHAR *)&fillst[j+mid],
                           sizeof(struct filnms));
               }
          }
     }
}

static VOID
gtnams(mdfnam,zirnam,i)            /* get file names & module name         */
CHAR *mdfnam;                      /*    .MDF file name for module         */
CHAR *zirnam;                      /*    .ZIR archive file name            */
INT i;                             /*    JSTONE, or where to put info      */
{
     struct filnms *fnams;
     CHAR *cp;

     if (i == JSTONE) {
          strupr(mdfnam);
          if (!samend(mdfnam,".MDF")) {
               strcat(mdfnam,".MDF");
          }
          strupr(zirnam);
          if (!samend(zirnam,".ZIR")) {
               strcat(zirnam,".ZIR");
          }
          fnams=&fnames;
     }
     else {
          fnams=&fillst[i];
     }
     stzcpy(fnams->zirnam,zirnam,strlen(zirnam)+1);
     strcpy(fnams->mlrnam,gmdfinf(mdfnam,"MSGs:"));
     if (sameas(mdfnam,"GALETL.MDF")) {
          if ((cp=strchr(fnams->mlrnam,',')) != NULL) {
               *cp = '\0';
          }
     }
     strcat(fnams->mlrnam,".MLR");
     stzcpy(fnams->ripnam,mdfnam+3,4);
     strcat(fnams->ripnam,"MNU.RIP");
     strcpy(modnam,gmdfinf(mdfnam,"Module Name:"));
     if (sameas(mdfnam,"GALETL.MDF") && sameas(modnam,"Teleconference")) {
          strcpy(modnam,ENTNAM);
     }
     if (i != JSTONE) {
          stzcpy((modlst[i]=alczer(strlen(modnam)+1)),modnam,
                 strlen(modnam)+1);
     }
}

static INT                         /*      1: got line ok     0: EOF       */
gcfgln(mdfnam,zirnam)              /* get line fm config file (deal w/ \n) */
CHAR *mdfnam;                      /*    where to put .MDF file name       */
CHAR *zirnam;                      /*      "   "   "  .ZIR  "    "         */
{
     CHAR *cp,cfgbuf[RBFSIZ];

     if (fgets(cfgbuf,RBFSIZ,cfgfil) == NULL) {
          return(0);
     }
     if (*(cp=cfgbuf+strlen(cfgbuf)-1) == '\n') {
          *cp='\0';
     }
     cp=strchr(cfgbuf,CFGSEP);
     stzcpy(mdfnam,cfgbuf,(INT)(cp-cfgbuf)+1);
     strcat(mdfnam,".MDF");
     stzcpy(zirnam,cp+1,strlen(cp+1)+1);
     strcat(zirnam,".ZIR");
     return(1);
}

static CHAR *
gmdfinf(mdfnam,pfix)               /* get info from line in .MDF file      */
CHAR *mdfnam;                      /*    .MDF file                         */
CHAR *pfix;                        /*    prefix to search for              */
{
     FILE *fp;
     static CHAR tmpbuf[RBFSIZ];

     if ((fp=fopen(mdfnam,FOPRA)) == NULL) {
          catastro("GMDFINF: CAN'T OPEN \"%s\"",mdfnam);
     }
     while (fgets(tmpbuf,sizeof(tmpbuf),fp) != NULL) {
          if (sameto(pfix,tmpbuf)) {
               unpad(tmpbuf);
               fclose(fp);
               return(skpwht(tmpbuf+strlen(pfix)));
          }
     }
     catastro("GMDFINF: unable to find string \"%s\" in %s!",pfix,mdfnam);
     return(tmpbuf);
}

static VOID
irip(modnam,fnams)                 /* install RIP for module               */
CHAR *modnam;                      /*    module name                       */
struct filnms fnams;               /*    needed file names                 */
{
     if (dozir(modnam,fnams)) {
          if (imprip(modnam,fnams)) {
               unlink(fnams.mlrnam);
               if (appmnu(modnam,fnams)) {
                    tellem(IMPAPP,modnam,fnams);
               }
               else {
                    tellem(IMPNAP,modnam,fnams);
               }
          }
          else {
               tellem(NOIMPT,modnam,fnams);
          }
     }
}

static INT
dozir(modnam,fnams)                /* unzip .ZIR file on hard drive        */
CHAR *modnam;                      /*     module name                      */
struct filnms fnams;               /*     file names info for this add-on  */
{
     INT pkrc;

     pushscn();
     if (!filxst(fnams.zirnam)) {
          explodeto(scntbl[1],0,11,50,19,15,8);
          pat(50,9,fnams.zirnam,0x4E,GVIDNOCURS);
          setatr(0x4F);
          printf("!");
          pat(17,13,modnam,0x4E,GVIDNOCURS);
          setatr(0x4F);
          printf(".");
          getchc();
          popscn();
          return(0);
     }
     explodeto(scntbl[1],51,0,68,3,32,10);
     pat(34,12,"Unzipping...",0x3F,GVIDNOCURS);
     if ((pkrc=spawnl(P_WAIT,"pkunzip.exe","","-#","-o",
                      fnams.zirnam,fnams.mlrnam,fnams.ripnam,NULL)) != 0) {
          catastro(spr("An error was encountered unzipping from %s:\n"
                       "PKUNZIP error number: %d",fnams.zirnam,pkrc));
     }
     popscn();
     return(1);
}

static INT
imprip(modnam,fnams)               /* import RIP into add-on's .MSG file   */
CHAR *modnam;                      /*    module name                       */
struct filnms fnams;               /*    file names info for this add-on   */
{
     CHAR *modchcs[]={
          " IMPORT ALL  - import all RIPscrip text blocks ",
          " IMPORT NEW  - import new RIPscrip text blocks only "
     };
     INT impmod;

     pushscn();
     explode(scntbl[2],9,0,70,24);
     pat(43,3,modnam,0x2E,GVIDNOCURS);
     setatr(0x2F);
     printf("?");
     pat(36,6,modnam,0x2E,GVIDNOCURS);
     setatr(0x2F);
     printf(",");
     pat(31,11,modnam,0x2E,GVIDNOCURS);
     setatr(0x2F);
     printf("'s text");
     if ((impmod=choose(2,modchcs,13,20,66,21,TRUE)*20) == (-ESC*20)) {
          popscn();
          return(0);
     }
     switch (impmod) {
     case IMPALL:
          system(spr("wgsilang %s olm /o",fnams.mlrnam));
          break;
     case IMPNEW:
          system(spr("wgsilang %s olm",fnams.mlrnam));
     }
     popscn();
     return(1);
}

static INT
appmnu(modnam,fnams)               /* append menu scene to any file        */
CHAR *modnam;                      /*    module name                       */
struct filnms fnams;               /*    file names for this add-on        */
{

     FILE *ripscn,*newscn,*appscn;
     INT fndend=0,cbfore,i;
     CHAR tnam[FNMSIZ],rdbuf[RBFSIZ],rdbuf2[RBFSIZ],*ynbuf="Yes",
          rscnnm[FNMSIZ];

     pushscn();
     explodeto(scntbl[4],0,10,64,23,7,5);
     pat(18,6,fnams.ripnam,0x3E,GVIDNOCURS);
     pat(46,11,fnams.ripnam,0x3E,GVIDNOCURS);
     pat(16,17,fnams.ripnam,0x3E,GVIDNOCURS);
     pat(44,9,modnam,0x3E,GVIDNOCURS);
     setatr(0x3F);
     printf(".");
     if (!edtval(32,17,4,ynbuf,validyn,MCHOICE) || ynbuf[0] == 'N') {
          popscn();
          return(0);
     }
     explodeto(scntbl[4],46,0,79,5,23,13);
     pat(25,15,fnams.ripnam,0x3E,GVIDNOCURS);
     rscnnm[0]='\0';
     if (!edtval(25,17,31,rscnnm,isfiln,0)) {
          popscn();
          return(0);
     }
     if ((ripscn=fopen(rscnnm,FOPRA)) == NULL) {
          catastro("APPMNU: Can't open %s for input!\n",rscnnm);
     }
     if ((appscn=fopen(fnams.ripnam,FOPRA)) == NULL) {
          catastro("APPMNU: Can't open %s for input!\n",fnams.ripnam);
     }
     tmpnam(tnam);
     if ((newscn=fopen(tnam,FOPWA)) == NULL) {
          catastro("APPMNU: Error creating temporary file %s!\n",tnam);
     }
     explodeto(scntbl[1],51,0,68,3,32,10);
     pat(34,12,"Appending...",0x3F,GVIDNOCURS);
     while (fgets(rdbuf,RBFSIZ,ripscn) != NULL) {
          if (!samein(RIP_NO_MORE,rdbuf) || fndend) {
               fputs(rdbuf,newscn);
          }
          else {
               if (!sameto("!|#",rdbuf)) {
                    cbfore=(INT)(strstr(rdbuf,"|#")-rdbuf);
                    for (i=0 ; i < cbfore ; i++) {
                         fputc(rdbuf[i],newscn);
                    }
                    fputc('\n',newscn);
               }
               while (fgets(rdbuf2,RBFSIZ,appscn) != NULL) {
                    fputs(rdbuf2,newscn);
               }
               fndend=1;
          }
     }
     fclose(ripscn);
     fclose(newscn);
     fclose(appscn);
     unlink(rscnnm);
     rename(tnam,rscnnm);
     popscn();
     return(1);
}

static VOID
tellem(whtdid,modnam,fnams)        /* messages for user concerning files */
INT whtdid;                        /*    imported graphics? app'ed menu? */
CHAR *modnam;                      /*    current module name             */
struct filnms fnams;               /*    file names for module           */
{
     pushscn();
     switch (whtdid) {
     case IMPAPP:
     case IMPNAP:
          explodeto(scntbl[3],0,15,63,22,8,8);
          pat(19,9,fnams.ripnam,0x3E,GVIDNOCURS);
          setatr(0x3F);
          if (whtdid == IMPAPP) {
               pat(65,9,".",0x3F,GVIDNOCURS);
               pat(10,10,"You can use this file as a reference, append it to "
                   "other",0x3F,GVIDNOCURS);
               pat(10,11,"scenes using RIPaint (if you have any further uses "
                   "for it),",0x3F,GVIDNOCURS);
               pat(10,12,"or delete it if you wish.",0x3F,GVIDNOCURS);
          }
          else {
               pat(65,9,",",0x3F,GVIDNOCURS);
               pat(10,10,"since you didn't choose to append it to an existing "
                   "scene at",0x3F,GVIDNOCURS);
               pat(10,11,"this time.  You can use this file as a reference, "
                   "append it",0x3F,GVIDNOCURS);
               pat(10,12,"to a scene using RIPaint, or delete it if you wish.",
                   0x3F,GVIDNOCURS);
          }
          break;
     case NOIMPT:
          explodeto(scntbl[3],0,0,63,13,8,5);
          pat(43,6,modnam,0x3E,GVIDNOCURS);
          setatr(0x3F);
          printf(sameas("Androids",modnam) ? "'" : "'s");
          pat(15,9,fnams.mlrnam,0x3E,GVIDNOCURS);
          pat(15,10,fnams.ripnam,0x3E,GVIDNOCURS);
     }
     getchc();
     popscn();
}

static INT
filxst(filnam)                     /* does this file exist?                */
CHAR *filnam;                           /* file to check on                */
{
     return(isfile(filnam));
}

static VOID
pushscn(VOID)                      /* save current screen                  */
{
     if (screens != NULL) {
          curscn=curscn->nxtscn=
                            (struct scninfo *)alcmem(sizeof(struct scninfo));
     }
     else {
          curscn=screens=(struct scninfo *)alcmem(sizeof(struct scninfo));
     }
     scn2mem(curscn->scn=alcmem(GVIDSCNSIZ),0,GVIDSCNSIZ);
     curscn->nxtscn=NULL;
}

static VOID
popscn(VOID)                       /* restore last saved screen            */
{
     struct scninfo *newcur;

     if (screens == NULL) {
          catastro("popscn: screen stack is empty...");
     }
     if (curscn != screens) {
          mem2scn(curscn->scn,0,GVIDSCNSIZ);
          free(curscn->scn);
          for (newcur=screens ; newcur->nxtscn->nxtscn != NULL
             ; newcur=newcur->nxtscn) {
          }
          newcur->nxtscn=NULL;
          free(curscn);
          curscn=newcur;
     }
     else {
          mem2scn(curscn->scn,0,GVIDSCNSIZ);
          free(curscn->scn);
          free(curscn);
          curscn=screens=NULL;
     }
}

static VOID
pat(x,y,pstg,atr,csiz)             /* print at spec loc, rel to 0,0        */
INT x,y;                           /*    location to print at              */
CHAR *pstg;                        /*    what to print                     */
INT atr;                           /*    fore/back attrib                  */
INT csiz;                          /*    what size cursor at end?          */
{
     proff(0,0);
     setatr(atr);
     cursiz(csiz);
     prat(x,y,"%s",pstg);
}

static VOID                        /* put module info in GALIARIP.CFG if   */
updcfg(mdfnam,zirnam)              /*  not there already                   */
CHAR *mdfnam;                      /*    .MDF file name                    */
CHAR *zirnam;                      /*    .ZIR file name                    */
{
     FILE *curcfg,*newcfg;
     CHAR tnam[FNMSIZ],cfgbuf[RBFSIZ],newone[8+1+8+1];

     if ((curcfg=fopen("GALIARIP.CFG",FOPRA)) == NULL) {
          return;
     }
     *(strchr(mdfnam,'.'))='\0';
     *(strchr(zirnam,'.'))='\0';
     while (fgets(cfgbuf,RBFSIZ,curcfg) != NULL) {
          if (sameto(mdfnam,cfgbuf)) {
               fclose(curcfg);
               return;
          }
     }
     tmpnam(tnam);
     if ((newcfg=fopen(tnam,FOPWA)) == NULL) {
          fclose(curcfg);
          return;
     }
     strcpy(newone,mdfnam);
     strcat(newone,"/");
     strcat(newone,zirnam);
     fprintf(newcfg,"%s\n",newone);
     rewind(curcfg);
     while (fgets(cfgbuf,RBFSIZ,curcfg) != NULL) {
          fprintf(newcfg,"%s",cfgbuf);
     }
     fclose(curcfg);
     fclose(newcfg);
     unlink("GALIARIP.CFG");
     rename(tnam,"GALIARIP.CFG");
}

static INT
xit(xitcod)                        /* shut down and display exit message   */
INT xitcod;                        /*    exit code                         */
{
     if (xitcod != NORIP) {
          popscn();
          locate(savx,savy);
          cursiz(scur);
          ansion(1);
          printf("\33[0m");
          if (xitcod == 0 || xitcod == NOINST) {
               updcfg(mdfnam,zirnam);
          }
     }
     clsvid();
     return(0);
}
