/***************************************************************************
 *                                                                         *
 *   WGSINT.CPP                                                            *
 *                                                                         *
 *   Copyright (c) 1987-1996 Galacticomm, Inc.    All Rights Reserved.     *
 *                                                                         *
 *   This is the integration-checker that should be run in the WG batch    *
 *   file just before firing up the server each time.  If there has been   *
 *   any change in time, date, or size on any of the .MDF files in the     *
 *   current directory, or any re-arrangement of them, or any change in    *
 *   the time, date, or size of WGSMENU2.DAT since the last time it ran,   *
 *   it goes into the more elaborate integration checking logic, and       *
 *   re-creates WGSERV.CFG, WGSUTL.REF, WGSMDF.REF, WGSINT.REF, and        *
 *   WGSMDFS.LST.  It also runs any install utilities referenced on        *
 *   "Install:" lines in MDF files, and it rebuilds WGSUSER.DOC from the   *
 *   components given in "Online user manual:" lines in MDF files.         *
 *   Finally, it creates WGSBTR.BAT, which is called out in WG.BAT to set  *
 *   up Btrieve with the proper pagesize and file-count parameters.        *
 *                                                                         *
 *                                            - T. Stryker 2/17/92         *
 *                                                                         *
 ***************************************************************************/

#include "stdafx.h"
#include "resource.h"
#include "sutldlg.h"
#include "catexcp.h"

#define ICOPATH "wgsicons"SLS"*.ico"    // system's icon directory/filespec
#define DEFICO  "wgsdef"                // default icon file name (no ext.)

struct iconew {                    // in-memory linked list of icon files
     CHAR name[FNSIZE];            //   file name, sans extension
     INT flags;                    //   #defined bitflags
     LONG size;                    //   file size
     INT date;                     //   file date, DOS format
     INT time;                     //   file time, DOS format
     struct iconew *next;          //   next element in list, or NULL if no
} *infirst=NULL;

#define ICOCHNGD 0x0001            // bitflag: icon has changed
#define ICOINLST 0x0002            // bitflag: icon is in WGSICONS.LST file

#define CFILBSZ  16384             // copy file buffer size

GBOOL redo=FALSE;                // flag: need to redo list and possibly menus

extern "C" DllImport GBOOL CheckReg(GBOOL isService);
static CHAR *choplast(CHAR *line);
static VOID copyvirs(VOID);
static GBOOL runUtil(const CHAR *pCmdLine);

VOID
copyActivehVirs(                   // copy Active HTML vir files as needed
const CHAR *dirname);              //   Active H directory to check

VOID
wgsint(VOID)
{
     Cffblk fb;
     INT i;
     GBOOL stest;
     CHAR *inp;
     FILE *fp;
     struct iconew *inltmp,*inlprv;

     CCatException* wgsExcept=new CCatException;

     setcrit();
     iconchek();
     stest=CheckReg(isService);
     if (!stest && isService) {
          wgsExcept->SetError(ERROR_FAIL,"Fatal error in wgsint() - "
               "Cannot enter activation code while another " SVR_NAME " "
               "process is running");
          THROW(wgsExcept);
     }
     else if (!stest) {
          wgsExcept->Delete();
          exit(200);
     }
     pST->SetWindowText("Updating HTML files...."); 
     copyvirs();
     if (anychg(TRUE)) {
          if ((fp=fopen("WGSCMAPS.FLG",FOPWA)) != NULL) {
               fprintf(fp,"Flag file: check apps for compression\n");
               fclose(fp);
          }
          iniint();
          wrtmjr();
          wrtact();
          pMW->ShowWindow(SW_HIDE);
          for (i=0 ; i < nmdfs ; i++) {
               inp=moddat[i].instal;
               if (*inp != '\0') {
                    if (isrunpgm(&fb,inp)) {
                         if (isService) {
                              wgsExcept->SetError(ERROR_FAIL,"Cannot launch install vectors while another "
                                   "" SVR_NAME " process is active");
                              THROW(wgsExcept);
                         }
                         runUtil(fb.ff_name);
                         unlink(fb.ff_name);
                         if (!refsok()) {
                              clrefs();
                              ctrefs();
                         }
                    }
               }
          }
          regntxt();
          finint();
          if (anychg(FALSE)) {
               iniint();
               finint();
          }
     }
     if (redo) {
          iconrev();
     }
     inlprv=infirst;
     while (inlprv != NULL) {
          inltmp=inlprv->next;
          free(inlprv);
          inlprv=inltmp;
     }
     wgsExcept->Delete();
     dfaStop();
}

VOID
regntxt(VOID)                 // regenerate WGSUSER.DOC from scratch
{
     CHAR *fname;
     CHAR tmp[256];
     INT mainum,i;
     CHAR *banner="Creating new WGSUSER.DOC....\n\n";

     pMW->ShowWindow(SW_SHOWNORMAL);
     pST->SetWindowText(banner);
     unlink("wgsuser.doc");
     if (*(fname=moddat[mainum=fndmod("Main Executive")].usrtxt) != '\0') {
          if (!cpyutl(fname,"wgsuser.doc",FOPRA,FOPWA)) {
               sprintf(tmp,"%sUnable to add the %s document file.",banner,fname);
               pST->SetWindowText(tmp);
          }
     }
     pPRG->SetRange(0,nmdfs-1);
     pPRG->SetPos(0);
     pPRG->SetStep(1);
     for (i=0 ; i < nmdfs ; i++) {
          if (i != mainum && *(fname=moddat[i].usrtxt) != '\0') {
               if (!cpyutl(fname,"wgsuser.doc",FOPRA,FOPAA)) {
                    sprintf(tmp,"%sUnable to append %s to WGSUSER.DOC.",banner,fname);
               }
          }
          pPRG->StepIt();
     }
     pPRG->SetPos(0);
     pST->SetWindowText(NULL);
}

INT
fndmod(                       // find a module's index (in moddat) by name
CHAR *modnam)                      // name of module to get index for
{
     INT i;

     CCatException* fmExcept=new CCatException;

     for (i=0 ; i < nmdfs ; i++) {
          if (sameas(modnam,moddat[i].modnam)) {
               fmExcept->Delete();
               return(i);
          }
     }
     fmExcept->SetError(ERROR_FAIL,"Fatal error in fndmod() - could not get index for module"
          "\"%s\"",modnam);
     THROW(fmExcept);
     return(0);
}

static VOID
copyvirs(VOID)                // copy .VIR files to .DATs where needed
{
     Cffblk fb;
     Cffblk fbd;
     CHAR datnam[GCMAXFNM];
     CHAR *pStr;

     if (fnd1st(&fb,GCVIRGIN"*.vir",0)) {
          do {
               memset(datnam,0,sizeof(datnam));
               memmove(datnam,fb.ff_name,findstg(".",fb.ff_name));
               strcat(datnam,"dat");
               if (!fnd1st(&fbd,datnam,0)) {
                    if ((pStr=strchr(datnam,'.')) != 0) {
                         *pStr='\0';
                    }
                    dfaVirgin(datnam,datnam);
               }
          } while (fndnxt(&fb));
     }

     //   find each active HTML directory and do VIR updates as needed
     //
     copyActivehVirs( "galacth" );
}

static
VOID
copyActivehVirs(                   // copy Active HTML vir files as needed
const CHAR *dirname)               //   Active H directory to check
{
     ASSERT( isdir( dirname ) );

     CHAR   virdir[ GCMAXPTH ];    // e.g. galacth/galfilah/vir
     CHAR   virmask[ GCMAXPTH ];   // e.g. galacth/galfilah/vir/*.*
     CHAR   virname[ GCMAXPTH ];   // e.g. galacth/galfilah/vir/root.htm
     CHAR   finalname[ GCMAXPTH ]; // e.g. galacth/galfilah/root.htm
     Cffblk fb;

     stlcpy( virdir, dirname, GCMAXPTH );
     stlcat( virdir, SLS "vir", GCMAXPTH );

     if (isdir( virdir ))
     {
          stlcpy( virmask, virdir, GCMAXPTH );
          stlcat( virmask, SLS "*.*", GCMAXPTH );

          if (fnd1st( &fb, virmask, 0 ))
          {
               do
               {
                    stlcpy( finalname, dirname, GCMAXPTH );
                    stlcat( finalname, SLS, GCMAXPTH );
                    stlcat( finalname, fb.ff_name, GCMAXPTH );

                    if (! isfile( finalname ))
                    {
                         stlcpy( virname, virdir, GCMAXPTH );
                         stlcat( virname, SLS, GCMAXPTH );
                         stlcat( virname, fb.ff_name, GCMAXPTH );
                         
                         ASSERT( isfile( virname ) );

                         if (! copyfile( virname, finalname ))
                         {
                              CCatException* except=new CCatException;

                              except->SetError(ERROR_FAIL,"Fatal error in copyActivehVirs() - could not copy virgin file"
                                   "\"%s\"",virname);
                              THROW(except);
                         }
                    }
               } while (fndnxt( &fb ));
          }
     }
     
     stlcpy( virdir, dirname, GCMAXPTH );
     stlcat( virdir, SLS "*.*", GCMAXPTH );

     if (fnd1st(&fb,virdir,FAMDIR)) {
          do {
               if (fb.ff_attrib&FAMDIR
                && !sameas(fb.ff_name,"vir")
                && !sameas(fb.ff_name,".")
                && !sameas(fb.ff_name,"..")) {
                    stlcpy(finalname,dirname,GCMAXPTH);
                    stlcat(finalname,SLS,GCMAXPTH);
                    stlcat(finalname,fb.ff_name,GCMAXPTH);
                    copyActivehVirs(finalname);
               }
          } while (fndnxt(&fb));
     }
}

// icon checking begins here

static CHAR *
choplast(                          // cut off last word in line,
CHAR *line)                        //   return the new last word
{
     CHAR *s;

     if ((s=lastwd(line)) != line) {
          s--;
          *s='\0';
          s=lastwd(line);
     }
     return(s);
}

VOID
iconchek(VOID)                     // check icon structure
{
     FILE *fp;
     Cffblk fb;
     CHAR fn[FNSIZE],*s;
     static CHAR line[100];
     INT tim,dat;
     LONG siz;
     struct iconew **inlcur,*inlprv;
     GBOOL listonly=TRUE;

     inlcur=&infirst;
     *inlcur=NULL;
     if (fnd1st(&fb,ICOPATH,0)) {
          do {
               stzcpy(fn,fb.ff_name,FNSIZE);
               if ((s=strchr(fn,'.')) != NULL) {
                    *s='\0';
               }
               *inlcur=(struct iconew *)alczer(sizeof(struct iconew));
               inlprv=*inlcur;
               inlprv->next=NULL;
               inlcur=&inlprv->next;
               stzcpy(inlprv->name,fn,FNSIZE);
               inlprv->size=fb.ff_fsize;
               inlprv->date=fb.ff_fdate;
               inlprv->time=fb.ff_ftime;
          } while (fndnxt(&fb));
     }
     if ((fp=fopen("wgsicons.lst",FOPRA)) != NULL) {
          while (fgets(line,sizeof(line),fp) != NULL) {
               if ((s=strchr(line,'\n')) != NULL) {
                    *s='\0';
               }
               s=lastwd(line);
               tim=atoi(s);
               s=choplast(line);
               dat=atoi(s);
               s=choplast(line);
               siz=atol(s);
               s=choplast(line);
               stzcpy(fn,s,FNSIZE);
               for (inlprv=infirst ; inlprv != NULL ; inlprv=inlprv->next) {
                    if (sameas(fn,inlprv->name)) {
                         inlprv->flags|=ICOINLST;
                         if (dat != inlprv->date
                          || tim != inlprv->time
                          || siz != inlprv->size) {
                              inlprv->flags|=ICOCHNGD;
                              listonly=FALSE;
                              redo=TRUE;
                         }
                         break;
                    }
               }
               if (inlprv == NULL) {
                    redo=TRUE;
               }
          }
          fclose(fp);
     }
     for (inlprv=infirst ; inlprv != NULL ; inlprv=inlprv->next) {
          if (!(inlprv->flags&ICOINLST)) {
               inlprv->flags|=ICOINLST;
               inlprv->flags|=ICOCHNGD;
               listonly=FALSE;
               redo=TRUE;
          }
     }
     if (redo) {
          pMW->ShowWindow(SW_SHOWNORMAL);
          if ((fp=fopen("wgsicons.lst",FOPWA)) != NULL) {
               for (inlprv=infirst ; inlprv != NULL ; inlprv=inlprv->next) {
                    fprintf(fp,"%s %ld %d %d\n",inlprv->name,
                                                inlprv->size,
                                                inlprv->date,
                                                inlprv->time);
               }
               fclose(fp);
          }
          if (listonly) {
               redo=FALSE;
          }
     }
}

VOID
iconrev(VOID)                      // review WGSMENU2.DAT for icons
{
     DFAFILE *bb;
     Cffblk fb;
     struct iconew *icoptr;
     CHAR key[PNMSIZ+1],*sptr;
     INT loop;
     GBOOL pagchg;
     static struct mnupag *mp;

     pMW->ShowWindow(SW_SHOWNORMAL);
     pST->SetWindowText("Reviewing Icons in WGSMENU2.DAT....");
     dfaMode(PRIMBV);
     mp=(struct mnupag *)alczer(sizeof(struct mnupag));
     bb=dfaOpen("wgsmenu2.dat",sizeof(struct mnupag),NULL);
     strcpy(key,"C");
     while (dfaAcqGT(mp,key,0) && mp->menutype[0] == key[0]) {
          stzcpy(&key[1],mp->pagnam,PNMSIZ);
          pagchg=FALSE;
          for (icoptr=infirst ; icoptr != NULL && !pagchg ; icoptr=icoptr->next) {
               if (!(mp->flags&(MDLPAG|FILPAG)) && (mp->flags&DFTDSP)
                && (icoptr->flags&ICOCHNGD)) {
                    for (loop=0 ; loop < mp->npages ; loop++) {
                         sptr=mp->page[loop].iconame;
                         if (sameas(sptr,icoptr->name)
                          || (sameas(DEFICO,icoptr->name)
                          && sptr[0] == '\0')) {
                              unpack(mp);
                              mp->ichange=time(NULL);
                              savepage(mp,FALSE);
                              pagchg=TRUE;
                              break;
                         }
                    }
               }
          }
     }
     dfaClose(bb);
     free(mp);
     fnd1st(&fb,"wgsmenu2.dat",0);
     markfile("wgsmenus.idx",&fb,FALSE);
     markfile("wgsmenuc.idx",&fb,FALSE);
     markfile("wgsint.ref",&fb,TRUE);
}

static GBOOL                       //   return TRUE-Ok
runUtil(                           // runs application
const CHAR *pCmdLine)              //   command line
{
     STARTUPINFO startInfo;
     PROCESS_INFORMATION procInfo;
     DWORD exitCode;

     memset(&startInfo,0,sizeof(STARTUPINFO));
     startInfo.cb=sizeof(STARTUPINFO);
     startInfo.lpTitle=(CHAR *)NULL;
     startInfo.dwFlags=STARTF_USESHOWWINDOW;
     startInfo.wShowWindow=(WORD)SW_SHOWDEFAULT;
     if (!CreateProcess(NULL,                // programm name
                        (LPTSTR)pCmdLine,    // command line string
                        NULL,                // process security attributes
                        NULL,                // thread security attributes
                        TRUE,                // handle inheritance flag
                        CREATE_DEFAULT_ERROR_MODE, // creation flags
                        NULL,                // new environment block
                        NULL,                // current directory name
                        &startInfo,          // STARTUPINFO
                        &procInfo)) {        // PROCESS_INFORMATION
          return(FALSE);
     }
     WaitForSingleObject(procInfo.hProcess,INFINITE);
     GetExitCodeProcess(procInfo.hProcess,&exitCode);
     CloseHandle(procInfo.hProcess);
     CloseHandle(procInfo.hThread);
     return(TRUE);
}
