/***************************************************************************
 *                                                                         *
 *   WGSCMAPS.C                                                            *
 *                                                                         *
 *   Copyright (c) 1996      Galacticomm, Inc.  All rights reserved.       *
 *                                                                         *
 *   This utility checks and shells to compress any and all files          *
 *    belonging to any C/S Apps.                                           *
 *                                                                         *
 *                                                - D. Pitchford  2/17/96  *
 *                                                                         *
 ***************************************************************************/

#include "stdafx.h"
#include "gcommlib.h"
#include "majorbbs.h"
#include "excphand.h"
#include "resource.h"
#include "HelpDialog.h"
#include "CheckingDialog.h"
#include "cmaps.h"

#define MAXAFL 1000                /* max # of files per path to compress  */
#define MAXCFL 5000                /* max # of files total to compress     */

BOOL quiet=FALSE;

static CHAR savscn[GVIDSCNSIZ];    /* DOS screen save area                 */

//extern CHAR scntbl[][GVIDSCNSIZ];  /* array of images via makescns         */

extern char *namptr;

struct finf {                      /* info on files extant in directories  */
     CHAR *name;                   /*   file name                          */
     INT date;                     /*        date                          */
     INT time;                     /*        time                          */
     LONG size;                    /*        size                          */
};



complog **clog = NULL;                   /* global array instance                */

UINT nlogd = 0;                    /* current number in **clog             */

static
INT savx,                          /* saved cursor position for restore    */
    savy;

static VOID procpth(CHAR *path);
static struct finf *inlist(GBOOL iscmp,CHAR *filnam,USHORT nlist,
                           struct finf **flist);
static VOID compress(CHAR *path,CHAR *filnam,LONG size);
static VOID dspbar(INT x,INT y,LONG num,LONG den);
static VOID prclog(VOID);
//static VOID dsphlp(VOID);
static CHAR *pathconv(const CHAR *path);
static VOID runCompress(CHAR *pCmdLine);

#if defined( CONSOLE_APP )
INT
main(                              /* main program loop                    */
int argc,                          /*   number of arguments                */
char *argv[])                      /*   the arguments                      */
{
TRY
     INT argcnt,num,napps,i;
     CHAR fname[FNEXSZ];
     CHAR **appids;
     CHAR *arg,*s;
#ifdef DEBUG
     struct ffblk fb;
#endif // DEBUG

#ifdef DEBUG
     if (fnd1st(&fb,"WGSCMAPS.LOG",0) && fb.ff_fsize > 65536L) {
          unlink("WGSCMAPS.LOG");
     }
#endif

#ifdef GCWINNT
     if (!canRunUtil()) {
          MessageBox(NULL,NOPROCEED,
                    argv[0],MB_ICONSTOP|MB_OK|MB_TASKMODAL|MB_SETFOREGROUND);
          return(1);
     }
#endif // GCWINNT
     initvid();
     if (argc == 1) {
          dsphlp();
          return(0);
     }
     for (argcnt=1 ; argcnt < argc ; argcnt++) {
          arg=argv[argcnt];
          if (sameas(arg,"/q") || sameas(arg,"-q")) {
               quiet=TRUE;
          }
          else if (sameas(arg,"/?") || sameas(arg,"-?")) {
               dsphlp();
               return(0);
          }
     }
     clog=(struct complog **)alczer(MAXCFL*sizeof(struct complog *));
     nlogd=0;
     scn2mem(savscn,0,GVIDSCNSIZ);
     savx=curcurx();
     savy=curcury();
     cursiz(GVIDNOCURS);
     cvtscn(scntbl[0]);
     for (argcnt=1 ; argcnt < argc ; argcnt++) {
          arg=argv[argcnt];
          if (sameas(arg,"/m") || sameas(arg,"-m")) {
               if ((num=tfsopn("*.mdf")) > 0) {
                    if (!quiet) {
                         explodeto(scntbl[0],0,6,30,10,25,9);
                    }
                    appids=(char **)alczer(num*sizeof(char *));
                    napps=0;
                    while (tfsrdl() != TFSDUN) {
                         if (tfstate == TFSLIN
                          && tfspfx("Client app EXE:")) {
                              stzcpy(fname,tfsfb.ff_name,FNEXSZ);
                              if ((s=strchr(fname,'.')) != NULL) {
                                   *s='\0';
                              }
                              appids[napps++]=alcdup(fname);
                         }
                    }
                    for (i=0 ; i < napps ; i++) {
                         procpth(appids[i]);
                         free(appids[i]);
                    }
                    free(appids);
               }
          }
          else if (sameas(arg,"/h") || sameas(arg,"-h")) {
               s=mstscan("WGSMAINM.MSG","HPSPP",200);
               if (s != NULL) {
                    procpth(pathconv(s));
               }
          }
          else {
               procpth(pathconv(arg));
          }
     }
     prclog();
     free(clog);
     mem2scn(savscn,0,GVIDSCNSIZ);
     cursiz(GVIDLILCURS);
     locate(savx,savy);
     return(0);
EXCEPT
#ifdef GCWINNT
     return(1);
#endif // GCWINNT
}
#endif


VOID
AddLocalFiles()
{
     if (clog == NULL)
     {
          clog=(struct complog **)alczer(MAXCFL*sizeof(struct complog *));
     }

     int       num = 0;
     CHAR **appids;
     INT napps,i;
     CHAR fname[FNEXSZ];
     char *s;

     if ((num=tfsopn("*.mdf")) > 0) {
          CheckingDialog *dlg = NULL;

          if (!quiet) {
               dlg = new CheckingDialog;
               dlg->Create( IDD_CHECKINGDIALOG );
          }
          appids=(char **)alczer(num*sizeof(char *));
          napps=0;
          while (tfsrdl() != TFSDUN) {
               if (tfstate == TFSLIN
                && tfspfx("Client app EXE:")) {
                    stzcpy(fname,namptr,FNEXSZ);
                    if ((s=strchr(fname,'.')) != NULL) {
                         *s='\0';
                    }
                    appids[napps++]=alcdup(fname);
               }
          }
          for (i=0 ; i < napps ; i++) {
               procpth(appids[i]);
               free(appids[i]);
          }
          free(appids);

          if (dlg != NULL)
          {
               dlg->OkToExit();
               delete dlg;
          }
     }
}


VOID
AddHypermediaFiles()
{
     if (clog == NULL)
     {
          clog=(struct complog **)alczer(MAXCFL*sizeof(struct complog *));
     }

     char *s=mstscan("WGSMAINM.MSG","HPSPP",200);
     if (s != NULL) {
          procpth(pathconv(s));
     }
}


VOID
ClearClog(VOID)
{
     if (clog != NULL)
     {
          for ( int count = 0; count < nlogd; ++count )
          {
               if (clog[ count ] != NULL)
               {
                    free( clog[ count ]->path );
                    free( clog[ count ]->name );
                    free( clog[ count ] );
               }
          }

          free( clog );
          clog = NULL;
     }

     clsmsgrdr();
}

VOID
AddFile(
const char *lpszParam)
{
     if (clog == NULL)
     {
          clog=(struct complog **)alczer(MAXCFL*sizeof(struct complog *));
     }

     procpth(pathconv(lpszParam));
}


static VOID
procpth(                           /* process appid or path                */
CHAR *path)                        /*   path to process                    */
{
     struct finf **reg,**cmp;
     INT nreg,ncmp;
//     struct ffblk fb;
     Cffblk fb;
     INT lstidx,inner;
     struct finf *fptr;
     CHAR *fname;

     nreg=ncmp=0;
     reg=(struct finf **)alczer(MAXAFL*sizeof(struct finf *));
     cmp=(struct finf **)alczer(MAXAFL*sizeof(struct finf *));
     if (fnd1st(&fb,spr("%s\\*.*",path),0)) {
          do {
               reg[nreg]=(struct finf *)alczer(sizeof(struct finf));
               reg[nreg]->name=alcdup(fb.ff_name);
               reg[nreg]->date=fb.ff_fdate;
               reg[nreg]->time=fb.ff_ftime;
               reg[nreg]->size=fb.ff_fsize;
               nreg++;
          } while (fndnxt(&fb));
     }
     for (lstidx=0 ; lstidx < nreg-1 ; lstidx++) {
          fname=alcdup(compfil(reg[lstidx]->name));
          for (inner=lstidx+1 ; inner < nreg ; inner++) {
               if (sameas(fname,compfil(reg[inner]->name))) {
                    free(reg[inner]->name);
                    *reg[inner]=*reg[--nreg];
                    free( reg[ nreg ] );  
                    free(reg[lstidx]->name);
                    *reg[lstidx--]=*reg[--nreg];
                    free( reg[ nreg ] );
                    break;
               }
          }
          free(fname);
     }
     if (fnd1st(&fb,spr("%s\\COMPRESS\\*.*",path),0)) {
          do {
               cmp[ncmp]=(struct finf *)alczer(sizeof(struct finf));
               cmp[ncmp]->name=alcdup(fb.ff_name);
               cmp[ncmp]->date=fb.ff_fdate;
               cmp[ncmp]->time=fb.ff_ftime;
               cmp[ncmp]->size=fb.ff_fsize;
               ncmp++;
          } while (fndnxt(&fb));
     }
     for (lstidx=0 ; lstidx < ncmp ; lstidx++) {
          if (inlist(TRUE,cmp[lstidx]->name,nreg,reg) == NULL) {
               fname=spr("%s\\COMPRESS\\%s",path,cmp[lstidx]->name);
               unlink(fname);
               free(cmp[lstidx]->name);
               *cmp[lstidx--]=*cmp[--ncmp];
               free(cmp[ncmp]);
          }
     }
     for (lstidx=0 ; lstidx < nreg ; lstidx++) {
          if (inlist(FALSE,reg[lstidx]->name,ncmp,cmp) == NULL) {
               compress(path,reg[lstidx]->name,reg[lstidx]->size);
               free(reg[lstidx]->name);
               *reg[lstidx--]=*reg[--nreg];
               free(reg[nreg]);
          }
     }
     for (lstidx=0 ; lstidx < nreg ; lstidx++) {
          fptr=inlist(FALSE,reg[lstidx]->name,ncmp,cmp);
          if (fptr->date == reg[lstidx]->date
           && fptr->time == reg[lstidx]->time) {
               free(reg[lstidx]->name);
               *reg[lstidx--]=*reg[--nreg];
               free(reg[nreg]);
          }
          free(fptr->name);
          *fptr=*cmp[--ncmp];
          free(cmp[ncmp]);
     }
     for (lstidx=0 ; lstidx < nreg ; lstidx++) {
          compress(path,reg[lstidx]->name,reg[lstidx]->size);
          free(reg[lstidx]->name);
          free(reg[lstidx]);
     }
     free(cmp);
     free(reg);
}

static struct finf *
inlist(                            /* is file name in list?                */
GBOOL iscmp,                       /*   is file name compressed?           */
char *filnam,                      /*   file name                          */
USHORT nlist,              /*   # of elements in list              */
struct finf **flist)               /*   list                               */
{
     INT i;

     if (iscmp) {
          for (i=0 ; i < nlist ; i++) {
               if (sameas(filnam,compfil(flist[i]->name))) {
                    return(flist[i]);
               }
          }
     }
     else {
          filnam=compfil(filnam);
          for (i=0 ; i < nlist ; i++) {
               if (sameas(filnam,flist[i]->name)) {
                    return(flist[i]);
               }
          }
     }
     return(NULL);
}

static VOID
compress(                          /* add file to "compress" list          */
CHAR *path,                        /*   path of file to add                */
CHAR *filnam,                      /*   file name                          */
LONG size)                         /*   size of file                       */
{
     clog[nlogd]=(struct complog *)alczer(sizeof(struct complog));
     clog[nlogd]->path=alcdup(path);
     clog[nlogd]->name=alcdup(filnam);
     clog[nlogd]->size=size;
     nlogd++;
}

CHAR *
compfil(                           /* return compressed file name          */
const CHAR *filnam)                      /*   file name, uncompressed            */
{
     CHAR *s;
     static CHAR retval[FNEXSZ];

     stlcpy(retval,filnam,FNEXSZ);
     s=strrchr(retval,'.');
     if (s == NULL) {
          stlcat(retval,"._",FNEXSZ);
     }
     else {
          if (strlen(s) == 4) {
               retval[strlen(retval)-1]='_';
          }
          else {
               stlcat(retval,"_",FNEXSZ);
          }
     }
     return(retval);
}

VOID
prclog(CWgscmapsDlg *dlg)                       /* process compress log                 */
{
     INT i;
     LONG totsize,szsofar;
     CHAR *path;

     totsize=0;
     for (i=0 ; i < nlogd ; i++) {
          totsize+=clog[i]->size;
     }
     if (nlogd > 0) {
//          explodeto(scntbl[0],0,0,74,4,2,9);
//          proff(0,0);
//          dspbar(4,12,0L,0L);
     }
     szsofar=0;
     for (i=0 ; i < nlogd ; i++) {
//          proff(0,0);
//          setatr(0x1E);
          path=spr("%s\\",clog[i]->path);
          if (strlen(path) > 9) {
               path="";
          }
//          prat(17,11,"%s%-24s",path,clog[i]->name);
//          szsofar+=clog[i]->size;
//          dspbar(4,12,szsofar,totsize); /* shown first on purpose */
          prccmp(clog[i]->path,clog[i]->name);
          free(clog[i]->path);
          free(clog[i]->name);
          free(clog[i]);
     }
}

VOID
prccmp(                            /* run compression utility              */
CHAR *path,
CHAR *filnam)
{
     CHAR *cfl;
//     struct ffblk fb;
     Cffblk fb;
     static GBOOL exists=FALSE;

     if (!exists) {
          if (!fnd1st(&fb,"WGSMSCOM.EXE",0)) {
               catastro("WGSCMAPS: WGSMSCOM.EXE NOT IN CURRENT DIRECTORY");
          }
          exists=TRUE;
     }
     runCompress(spr("WGSMSCOM.EXE /r %s\\%s >NUL",path,filnam));
     mkdir(spr("%s\\COMPRESS",path));
     cfl=compfil(filnam);
     unlink(spr("%s\\COMPRESS\\%s",path,cfl));
     rename(spr("%s\\%s",path,cfl),
            spr("%s\\COMPRESS\\%s",path,cfl));
}

VOID
dsphlp(VOID)
{
     HelpDialog dlg;

     dlg.DoModal();
}

static CHAR *
pathconv(                          /* remove trailing slash from path      */
const CHAR *path)                        /*   if any                             */
{
     INT i;
     CHAR *c;
     static CHAR retpath[GCMAXPTH];

     stzcpy(retpath,path,GCMAXPTH);
     i=strlen(retpath);
     c=i > 0 ? &retpath[i-1] : "";
     if (*c == '\\' || *c == '/') {
          *c='\0';
     }
     return(retpath);
}

static VOID
runCompress(
CHAR *pCmdLine)
{
     system(pCmdLine);
}