/***************************************************************************
 *                                                                         *
 *   WGSDMOD.C                                                             *
 *                                                                         *
 *   Copyright (c) 1991-1997 Galacticomm, Inc.    All Rights Reserved.     *
 *                                                                         *
 *   This is the utility to enable/disable modules (c/o .MDF and .DMD).    *
 *                                                                         *
 *                                                 - C. Robert 3/13/92     *
 *                                                                         *
 ***************************************************************************/

#include "gcomm.h"
#include "majorbbs.h"
#include "excphand.h"

#define FILREV "$Revision: 9 $"

#define INCSIZ      100       /* # of modules to (re)allocate for at a time*/

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

extern SHORT fstchc;          /* first guy displayed in window             */
extern SHORT curchc;          /* current guy selected in window            */

INT scur1,scur2,sfst1,sfst2;  /* saved current and first displayed choices */

CHAR dosscn[GVIDSCNSIZ];      /* save-screen buffer for old DOS screen     */

struct moddat {               /* module definition file data area          */
     CHAR mdfnam[FNMSIZ];          /* name of .MDF (or .DMD) file w/o ext  */
} **mdfdat,                   /* array of all module definition file info  */
  **dmddat;                   /* array of all disabled module info         */

CHAR **modnam,                /* array of enabled module names             */
     **dmdnam;                /* array of disabled module names            */

INT nmods=0;                  /* number of enabled modules                 */
INT mmods=INCSIZ;             /* memory for how many enabled modules?      */
INT ndmods=0;                 /* number of disabled modules                */
INT mdmods=INCSIZ;            /* memory for how many disabled modules?     */

INT enabling=0;               /* now enabling modules?                     */

static VOID lodmdf(VOID) ;
static VOID loddmd(VOID) ;
static VOID ckmdrm(VOID) ;
static VOID ckdmrm(VOID) ;
static VOID dismod(INT modnum);
static VOID enamod(INT modnum);
static INT mychoo(INT n,CHAR *chcs[],INT upx,INT upy,INT lox,INT loy,GBOOL escok);
static VOID mysupc(INT n,CHAR *chcs[],INT upx,INT upy,INT lox,INT loy,GBOOL escok);
static VOID dspmod(VOID) ;
static VOID dspdmd(VOID) ;
static VOID savpos(INT select);
static VOID fixdups(VOID) ;
static INT cntthm(CHAR *which);
static VOID srtmod(INT srtena);
static CHAR *zapprn(CHAR *stg);
static VOID sortem(CHAR *stgs[],INT num,struct moddat *mdfs[]);

INT
main(                               /* main program entry point             */
INT argc,
CHAR *argv[])
{
TRY
     INT cnum,done=0;

     (VOID)argc;
#ifdef GCWINNT
     if (!canRunUtil()) {
          MessageBox(NULL,NOPROCEED,
                    argv[0],MB_ICONSTOP|MB_OK|MB_TASKMODAL|MB_SETFOREGROUND);
          return(1);
     }
#else
     (VOID)argv;
#endif // GCWINNT
     initvid();
     scn2mem(dosscn,0,GVIDSCNSIZ);
     cvtscn(scntbl[0]);
     modnam=(CHAR **)alcmem(sizeof(CHAR *)*mmods);
     dmdnam=(CHAR **)alcmem(sizeof(CHAR *)*mdmods);
     mdfdat=(struct moddat **)alcmem(sizeof(struct moddat *)*mmods);
     dmddat=(struct moddat **)alcmem(sizeof(struct moddat *)*mdmods);
     lodmdf();
     loddmd();
     fixdups();
     srtmod(0);
     srtmod(1);
     cursiz(GVIDNOCURS);
     explode(scntbl[0],0,0,79,24);
     proff(0,0);
     if (nmods == 0 && ndmods == 0) {
          catastro("NO MODULES DEFINED (ENABLED OR DISABLED)!");
     }
     selatr=0x7E;
     nslatr=0x3E;
     if (ndmods) {
          dspdmd();
     }
     while (!done) {
          if (nmods) {
               while (nmods) {
                    cnum=mychoo(nmods,modnam,3,6,37,19,FALSE);
                    savpos(cnum >= 0);
                    if (cnum == -ALT_X) {
                         done=1;
                         break;
                    }
                    else if (cnum == -TAB) {
                         break;
                    }
                    else {
                         dismod(cnum);
                         dspdmd();
                    }
               }
               dspmod();
          }
          if (!done && ndmods) {
               enabling=1;
               while (ndmods) {
                    cnum=mychoo(ndmods,dmdnam,42,6,76,19,FALSE);
                    savpos(cnum >= 0);
                    if (cnum == -ALT_X) {
                         done=1;
                         break;
                    }
                    else if (cnum == -TAB) {
                         break;
                    }
                    else {
                         enamod(cnum);
                         dspmod();
                    }
               }
               enabling=0;
               dspdmd();
          }
     }
     setatr(0x07);
     printf(" ");
     locate(0,24);
     mem2scn(dosscn,0,GVIDSCNSIZ);
     cursiz(GVIDLILCURS);
     clsvid();
     return(0);
EXCEPT
#ifdef GCWINNT
     return(1);
#endif // GCWINNT
}

static VOID
lodmdf(VOID)                        /* load the .MDF files                  */
{
     struct ffblk fb;
     FILE *fp;
     CHAR mdfbuf[100];

     nmods=0;
     if (fnd1st(&fb,"*.mdf",0)) {
          do {
               if ((fp=fopen(fb.ff_name,FOPRA)) == NULL) {
                    catastro("CAN'T OPEN \"%s\" FOR READING!",fb.ff_name);
               }
               while (fgets(mdfbuf,sizeof(mdfbuf),fp) != NULL) {
                    unpad(mdfbuf);
                    if (mdfbuf[0] != ';' && sameto("Module Name:",mdfbuf)) {
                         ckmdrm();
                         mdfdat[nmods]=(struct moddat *)alcmem(
                                                         sizeof(struct moddat));
                         stzcpy(mdfdat[nmods]->mdfnam,skpwht(mdfbuf+12),MNMSIZ);
                         modnam[nmods]=alcmem(strlen(mdfdat[nmods]->mdfnam)+1);
                         strcpy(modnam[nmods],mdfdat[nmods]->mdfnam);
                         stzcpy(mdfdat[nmods]->mdfnam,fb.ff_name,MNMSIZ);
                         mdfdat[nmods]->mdfnam[strlen(fb.ff_name)-4]='\0';
                         nmods++;
                    }
               }
               fclose(fp);
          } while (fndnxt(&fb));
     }
}

static VOID
loddmd(VOID)                        /* load the .DMD files                  */
{
     struct ffblk fb;
     FILE *fp;
     CHAR mdfbuf[100];

     ndmods=0;
     if (fnd1st(&fb,"*.dmd",0)) {
          do {
               if ((fp=fopen(fb.ff_name,FOPRA)) == NULL) {
                    catastro("CAN'T OPEN \"%s\" FOR READING!",fb.ff_name);
               }
               while (fgets(mdfbuf,sizeof(mdfbuf),fp) != NULL) {
                    unpad(mdfbuf);
                    if (mdfbuf[0] != ';' && sameto("Module Name:",mdfbuf)) {
                         ckdmrm();
                         dmddat[ndmods]=(struct moddat *)alcmem(
                                                          sizeof(struct moddat));
                         stzcpy(dmddat[ndmods]->mdfnam,skpwht(mdfbuf+12),MNMSIZ);
                         dmdnam[ndmods]=alcmem(strlen(dmddat[ndmods]->mdfnam)+1);
                         strcpy(dmdnam[ndmods],dmddat[ndmods]->mdfnam);
                         stzcpy(dmddat[ndmods]->mdfnam,fb.ff_name,MNMSIZ);
                         dmddat[ndmods]->mdfnam[strlen(fb.ff_name)-4]='\0';
                         ndmods++;
                    }
               }
               fclose(fp);
          } while (fndnxt(&fb));
     }
}

static VOID
ckmdrm(VOID)                        /* check enabled module room            */
{
     if (nmods+1 > mmods) {
          modnam=(CHAR **)alcrsz(modnam,sizeof(CHAR *)*mmods,
                                sizeof(CHAR *)*(mmods+INCSIZ));
          mdfdat=(struct moddat **)alcrsz(mdfdat,sizeof(struct moddat *)*mmods,
                                       sizeof(struct moddat *)*(mmods+INCSIZ));
          mmods+=INCSIZ;
     }
}

static VOID
ckdmrm(VOID)                        /* check disabled module room           */
{
     if (ndmods+1 > mdmods) {
          dmdnam=(CHAR **)alcrsz(dmdnam,sizeof(CHAR *)*mdmods,
                                sizeof(CHAR *)*(mdmods+INCSIZ));
          dmddat=(struct moddat **)alcrsz(dmddat,sizeof(struct moddat)*mdmods,
                                        sizeof(struct moddat)*(mdmods+INCSIZ));
          mdmods+=INCSIZ;
     }
}

static VOID
dismod(                            /* disable a module                     */
INT modnum)                        /*   module number to disable           */
{
     CHAR fname[FNMSIZ],fname2[FNMSIZ];

     strcpy(fname,mdfdat[modnum]->mdfnam);
     strcpy(fname2,fname);
     strcat(fname,".MDF");
     strcat(fname2,".DMD");
     _rtl_chmod(fname2,1,0);
     unlink(fname2);
     rename(fname,fname2);
     ckdmrm();
     dmdnam[ndmods]=modnam[modnum];
     dmddat[ndmods]=mdfdat[modnum];
     ndmods++;
     srtmod(0);
     if (modnum != nmods-1) {
          movmem(&modnam[modnum+1],&modnam[modnum],sizeof(CHAR *)
                                                   *(nmods-modnum-1));
          movmem(&mdfdat[modnum+1],&mdfdat[modnum],sizeof(struct moddat *)
                                                   *(nmods-modnum-1));
     }
     nmods--;
}

static VOID
enamod(                            /* enable a module                      */
INT modnum)                        /*   module number to enable            */
{
     CHAR fname[FNMSIZ],fname2[FNMSIZ];

     strcpy(fname,dmddat[modnum]->mdfnam);
     strcpy(fname2,fname);
     strcat(fname,".DMD");
     strcat(fname2,".MDF");
     _rtl_chmod(fname2,1,0);
     unlink(fname2);
     rename(fname,fname2);
     ckmdrm();
     modnam[nmods]=dmdnam[modnum];
     mdfdat[nmods]=dmddat[modnum];
     nmods++;
     srtmod(1);
     if (modnum != ndmods-1) {
          movmem(&dmdnam[modnum+1],&dmdnam[modnum],sizeof(CHAR *)
                                                   *(ndmods-modnum-1));
          movmem(&dmddat[modnum+1],&dmddat[modnum],sizeof(struct moddat *)
                                                   *(ndmods-modnum-1));
     }
     ndmods--;
}

static INT
mychoo(                              /* have user pick one of the choices */
INT n,                               /*   number of choices offered user  */
CHAR *chcs[],                        /*   text of choices offered to user */
INT upx,                             /*   upper-left x coordinate         */
INT upy,                             /*   upper-left y coordinate         */
INT lox,                             /*   lower-right x coordinate        */
INT loy,                             /*   lower-right y coordinate        */
GBOOL escok)                         /*   accept an ESCAPE to quit?       */
{
     INT c,retval;

     mysupc(n,chcs,upx,upy,lox,loy,escok);
     fstchc=(enabling ? sfst2 : sfst1);
     curchc=(enabling ? scur2 : scur1);
     dspchc();
     do {
          c=getchc();
          if (c == TAB || c == CRSRRT || c == CRSRLF || c == BAKTAB) {
               retval=-TAB;
               break;
          }
          else if (c == ALT_X) {
               retval=-ALT_X;
               break;
          }
     } while ((retval=hdlchc(c)) == n);
     return(retval);
}

static VOID
dspmod(VOID)                        /* display the enabled modules          */
{
     mysupc(nmods,modnam,3,6,37,19,FALSE);
     curchc=9999;
     fstchc=sfst1;
     dspchc();
}

static VOID
dspdmd(VOID)                        /* display the disabled modules         */
{
     mysupc(ndmods,dmdnam,42,6,76,19,FALSE);
     curchc=9999;
     fstchc=sfst2;
     dspchc();
}

static VOID
savpos(                            /* save current position in window      */
INT select)                        /*   selected current guy?              */
{
     INT nguys,newcur,newfst;

     newfst=fstchc;
     newcur=curchc;
     if (select) {
          nguys=(enabling ? ndmods : nmods);
          if (newcur != 0 && newcur == nguys-1) {
               newcur--;
          }
          if (newfst != 0 && newfst+14 >= nguys) {
               newfst--;
          }
     }
     if (!enabling) {
          sfst1=newfst;
          scur1=newcur;
     }
     else {
          sfst2=newfst;
          scur2=newcur;
     }
}

static VOID
mysupc(                              /* set-up to offer choices to user    */
INT n,                               /*   number of choices offered user   */
CHAR *chcs[],                        /*   text of choices offered to user  */
INT upx,                             /*   upper-left x coordinates         */
INT upy,                             /*   upper-left y coordinates         */
INT lox,                             /*   lower-right x coordinates        */
INT loy,                             /*   lower-right y coordinates        */
GBOOL escok)                         /*   accept an ESCAPE to quit?        */
{
     mem2scn(scntbl[0]+gvscnoff(upx,loy+1),gvscnoff(upx,loy+1),
                                        (lox-upx+1)*2);
     supchc(n,chcs,upx,upy,lox,loy,escok);
}

static VOID
fixdups(VOID)                       /* fix-up duplicate module names        */
{
     INT i;

     for (i=0 ; i < nmods ; i++) {
          if (cntthm(modnam[i]) > 1) {
               modnam[i]=alcrsz(modnam[i],strlen(modnam[i])+1,
                                strlen(modnam[i])+11+1);
               strcat(modnam[i],spr(" (%s)",mdfdat[i]->mdfnam));
          }
     }
     for (i=0 ; i < ndmods ; i++) {
          if (cntthm(dmdnam[i]) > 1) {
               dmdnam[i]=alcrsz(dmdnam[i],strlen(dmdnam[i])+1,
                                strlen(dmdnam[i])+11+1);
               strcat(dmdnam[i],spr(" (%s)",dmddat[i]->mdfnam));
          }
     }
}

static INT
cntthm(                            /* count occurences of a mod name       */
CHAR *which)
{
     CHAR temp[40];
     INT i,retval=0;

     strcpy(temp,zapprn(which));
     for (i=0 ; i < nmods ; i++) {
          if (sameas(zapprn(modnam[i]),temp)) {
               retval++;
          }
     }
     for (i=0 ; i < ndmods ; i++) {
          if (sameas(zapprn(dmdnam[i]),temp)) {
               retval++;
          }
     }
     return(retval);
}

static VOID
srtmod(                            /* sort list of module names            */
INT srtena)                        /*   sort enabled ones? (1 or 0)        */
{
     sortem(srtena ? modnam : dmdnam,srtena ? nmods : ndmods,
            srtena ? mdfdat : dmddat);
}

static CHAR *
zapprn(                            /* zap the ()'s at the end of a stg     */
CHAR *stg)                         /*   stg to zap                         */
{
     INT i;
     static CHAR temp[40];

     strcpy(temp,stg);
     for (i=1 ; i < strlen(temp) ; i++) {
          if (temp[i] == '(' && temp[i-1] == ' ') {
               temp[i-1]='\0';
               break;
          }
     }
     return(temp);
}

static VOID
sortem(                            /* do a quick shell-sort on array of $'s*/
CHAR *stgs[],                      /*   array of strings to sort           */
INT num,                           /*   number of strings to sort          */
struct moddat *mdfs[])             /*   array of .MDF data struct ptrs     */
{
     CHAR *hold;
     INT mid,i,j;
     struct moddat *mhold;

     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(stgs[j],stgs[j+mid]) <= 0) {
                         break;
                    }
                    hold=stgs[j];
                    mhold=mdfs[j];
                    stgs[j]=stgs[j+mid];
                    stgs[j+mid]=hold;
                    mdfs[j]=mdfs[j+mid];
                    mdfs[j+mid]=mhold;
               }
          }
     }
}
