/***************************************************************************
 *                                                                         *
 *   GALFOMAN.C                                                            *
 *                                                                         *
 *   Copyright (c) 1996-1997 Galacticomm, Inc.        All Rights Reserved. *
 *                                                                         *
 *   This is the offline Forums management utility.  An undocumented       *
 *   feature exists to sequence your Forums in sorted order: just pass a   *
 *   command-line parameter of "sort".  (This is undocumented since Forums *
 *   should default to sorted order under normal operating conditions.)    *
 *                                                                         *
 *                                                 - C. Robert 12/6/94     *
 *                                                                         *
 ***************************************************************************/

#include "gcomm.h"
#include "majorbbs.h"
#include "gme.h"
#include "gmeutl.h"
#include "gmeloc.h"
#include "gmeoff.h"
#include "protstuf.h"
#include "excphand.h"

#define FILREV "$Revision: 15 $"

#define NUMSCN  6                  /* number of screen images we're using  */
#define NUMCHC  3                  /* number of main menu choices          */
#define NUMSIZ  4                  /* max length of temp number string     */
#define RETURN  13                 /* carriage return ASCII code           */
#define SRTSTR  "SORT"             /* command line arg to trigger sort     */
#define DATEXT  "dat"              /* extension for forum data files       */
#define FORDEFN "galfdef2.dat"     /* definition file name (from GMELOC.C) */

                                   /* choose() return values               */
#define MOVFOR 0                   /*   moving forum to another .DAT file  */
#define CHGDAT 1                   /*   changing max number of .DAT files  */
#define EXTPRG 2                   /*   exiting Forum Manager              */

                                   /* movstt/numstt codes                  */
#define GETNAM 0                   /*   currently getting forum name       */
#define GETPTH 1                   /*   currently getting forum path       */
#define GETNUM 2                   /*   currently getting # of data files  */
#define GETOUT 3                   /*   get out of the current operation   */

INT numdat;                        /* number of .DAT files to support      */

USHORT formid;                     /* Forum identifier                     */

GBOOL updfors=FALSE;               /* do Forums on disk need updating?     */
GBOOL infmgr=TRUE;                 /* are we still in Forum Manager?       */

CHAR prgscn[GVIDSCNSIZ];           /* save area for in-program screen      */
CHAR fornam[FORNSZ];               /* forum name to move to another .DAT   */
CHAR tmpnum[NUMSIZ];               /* temporary number string (for edtval) */
CHAR filpth[MAXDFAP];              /* path+file of new forum .DAT file     */

CHAR *fmchcs[NUMCHC]={             /* forum manager list of choices        */
     "   Move forum from one .DAT file to another    ",
     "Define maximum number of .DAT files to support ",
     "              Exit Forum Manager               "
};

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

static VOID rstdscn(VOID);
static GBOOL valfor(INT c);
static GBOOL valpth(INT c);
static VOID wait4cr(VOID);
static VOID repmsg(LONG msgno);
static VOID crepth(CHAR *path);
static VOID sortfors(VOID);
static CHAR *odfnam(USHORT forum);
static GBOOL vfyndf(USHORT forum,CHAR *ndfil);
static GBOOL chgfdf(USHORT forum,CHAR *ndfil);
static VOID deferr(VOID);
static VOID filerr(CHAR *filmsg);
static VOID emlerr(VOID);
static VOID samerr(VOID);
static VOID lmterr(VOID);

INT
main(                              /* main program loop                    */
INT argc,                          /*   number of command-line args        */
CHAR *argv[])                      /*   array of command-line args         */
{
TRY
     INT loop,keyhit,movstt,numstt;
     GBOOL updnum,movfor,chgnum;
     CHAR fptmp[GCMAXFNM];

#ifdef GCWINNT
     if (!canRunUtil()) {
          MessageBox(NULL,NOPROCEED,
                    argv[0],MB_ICONSTOP|MB_OK|MB_TASKMODAL|MB_SETFOREGROUND);
          return(1);
     }
#endif // GCWINNT
     protinit("GALFOMAN ");
     initvid();
     cursiz(GVIDNOCURS);
     rstdscn();
     explodeto(scntbl[1],0,17,33,21,22,10);
     iniogme();
     monorcol();
     for (loop=0 ; loop < NUMSCN ; loop++) {
          cvtscn(scntbl[loop]);
     }
     rstdscn();
     if (argc == 2 && sameas(argv[1],SRTSTR)) {
          explodeto(scntbl[2],0,0,29,4,24,10);
          sortfors();
     }
     else {
          while (infmgr) {
               rstdscn();
               explodeto(scntbl[1],0,0,55,16,12,4);
               movstt=GETNAM;
               numstt=GETNUM;
               movfor=TRUE;
               chgnum=TRUE;
               switch (choose(NUMCHC,fmchcs,5,11,50,13,TRUE)) {
               case MOVFOR:
                    while (movfor) {
                         switch (movstt) {
                         case GETNAM:
                              rstdscn();
                              explodeto(scntbl[2],0,5,66,9,6,10);
                              fornam[0]='\0';
                              if (!edtval(49,2,FORNSZ,fornam,valfor,USEPOFF)) {
                                   movstt=GETOUT;
                                   break;
                              }
                              if (strlen(fornam) == 0) {
                                   movstt=GETOUT;
                                   break;
                              }
                              if ((formid=getfid(fornam)) == EMLID) {
                                   printf("\7");
                                   explodeto(scntbl[2],0,10,29,16,25,7);
                                   wait4cr();
                                   movstt=GETNAM;
                                   break;
                              }
                         case GETPTH:
                              rstdscn();
                              explodeto(scntbl[3],0,0,60,8,10,10);
                              setatr(0x1E);
                              prat(3,3,"%s",odfnam(formid));
                              filpth[0]='\0';
                              if (!edtval(3,6,MAXDFAP,filpth,valpth,
                                      needupc() ? ALLCAPS+USEPOFF : USEPOFF)) {
                                   movstt=GETOUT;
                                   break;
                              }
                              if (sameas(fileparts(GCPART_EXTN,filpth,fptmp,
                                                   GCMAXFNM),DATEXT)
                               && strlen(fileparts(GCPART_FNAM,filpth,fptmp,
                                                   GCMAXFNM))
                                >= sizeof("x." DATEXT)-1) {
                                   crepth(filpth);
                              }
                              else {
                                   printf("\7");
                                   explodeto(scntbl[5],0,0,36,9,21,7);
                                   wait4cr();
                                   movstt=GETPTH;
                                   break;
                              }
                              if (vfyndf(formid,filpth)) {
                                   rstdscn();
                                   explodeto(scntbl[3],0,9,53,19,13,10);
                                   setatr(0x1E);
                                   prat(23,5,"%s",fornam);
                                   if (chgfdf(formid,filpth)) {
                                        setatr(0x1E);
                                        prat(9,8,"Finished!  "
                                             "Press RETURN to continue.");
                                        wait4cr();
                                        movstt=GETOUT;
                                        break;
                                   }
                                   else {
                                        printf("\7");
                                        explodeto(scntbl[2],30,10,76,16,16,7);
                                        wait4cr();
                                        movstt=GETPTH;
                                        break;
                                   }
                              }
                              else {
                                   movstt=GETOUT;
                              }
                         case GETOUT:
                              movfor=FALSE;
                              break;
                         }
                    }
                    break;
               case CHGDAT:
                    while (chgnum) {
                         switch (numstt) {
                         case GETNUM:
                              rstdscn();
                              explodeto(scntbl[4],0,0,62,6,8,10);
                              setatr(0x1E);
                              prat(51,2,"%d",gnumdb(GMEMDF));
                              tmpnum[0]='\0';
                              if (!edtval(57,4,NUMSIZ,tmpnum,validig,USEPOFF)) {
                                   numstt=GETOUT;
                                   break;
                              }
                              if ((numdat=atoi(tmpnum)) < 1 || numdat > 512) {
                                   printf("\7");
                                   explodeto(scntbl[2],0,17,42,23,18,7);
                                   wait4cr();
                                   numstt=GETNUM;
                                   break;
                              }
                              updnum=TRUE;
                              if (numdat >= 50) {
                                   printf("\7");
                                   explodeto(scntbl[5],0,10,59,21,10,7);
                                   do {
                                        keyhit=getchc();
                                        if (keyhit == ESC) {
                                             updnum=FALSE;
                                             keyhit=13;
                                        }
                                   } while (keyhit != 13);
                              }
                              if (updnum) {
                                   snumdb(GMEMDF,numdat);
                                   numstt=GETOUT;
                              }
                              else {
                                   numstt=GETNUM;
                                   break;
                              }
                         case GETOUT:
                              chgnum=FALSE;
                              break;
                         }
                    }
                    break;
               case -ESC:
               case EXTPRG:
                    infmgr=FALSE;
                    break;
               }
          }
     }
     if (updfors) {
          rstdscn();
          explodeto(scntbl[1],34,17,68,21,21,10);
     }
     rstdscn();
     clsogme(updfors);
     locate(0,24);
     cursiz(GVIDLILCURS);
     clsvid();
     return(0);
EXCEPT
#ifdef GCWINNT
     return(1);
#endif
}

static VOID
rstdscn(VOID)                      /* restore DOS screen image (intro scn) */
{
     mem2scn(scntbl[0],0,GVIDSCNSIZ);
}

static GBOOL
valfor(                            /* edtval() valrou for Forum name       */
INT c)
{
     return((c > 32 && c <= 127) && c != '/' && c != ';' && c != '@');
}

static GBOOL
valpth(                            /* edtval() valrou for path+file name   */
INT c)
{
     return((c <= 255 && isalnum(c)) || c == '!' || c == '@' || c == '#'
         || c == '$' || c == '%' || c == '^' || c == '&' || c == '('
         || c == ')' || c == '-' || c == '_' || c == '+' || c == '='
         || c == '.' || c == ':' || c == '\\');
}

static VOID
wait4cr(VOID)                      /* wait until carriage return is hit    */
{
     do {
     } while (getchc() != RETURN);
}

static VOID
repmsg(                            /* report progress                      */
LONG msgno)                        /*   message number to report           */
{
     setatr(0x1E);
     prat(26,6,"%-11.11s",l2as(msgno));
}

static VOID
crepth(                            /* creates data file path (if needed)   */
CHAR *path)
{
     CHAR tmppth[GCMAXPTH],fptmp[GCMAXPTH];

     stlcpy(tmppth,fileparts(GCPART_PATH,path,fptmp,GCMAXPTH),GCMAXPTH);
     if (!isdir(tmppth)) {
          gmkdir(tmppth);
     }
}

static VOID
deferr(VOID)                       /* pop up "can't use def file" error    */
{
     filerr("the Forum Definition data file.");
}

static VOID
emlerr(VOID)                       /* pop up "can't use E-mail file" error */
{
     filerr("the E-mail data file.");
}

static VOID
filerr(                            /* pop up "Error! Invalid file!" error  */
CHAR *filmsg)                      /*   specific file message              */
{
     printf("\7");
     explodeto(scntbl[5],37,0,77,8,21,8);
     setatr(0x4F);
     prat(3,4,filmsg);
     wait4cr();
}

static VOID
samerr(VOID)                       /* pop up "files are same" error        */
{
     printf("\7");
     explodeto(scntbl[4],0,7,43,13,17,7);
     wait4cr();
}

static VOID
lmterr(VOID)                       /* pop up "reached data file limit" err */
{
     printf("\7");
     explodeto(scntbl[4],0,14,49,23,15,7);
     wait4cr();
}

static VOID
sortfors(VOID)                     /* sequence all Forums by sort order    */
{
     INT i;

     for (i=0 ; i < numforums() ; i++) {
          idxdef(i)->seqid=i;
     }
     updfors=TRUE;
}

static CHAR *
odfnam(                            /* get old (current) data file path     */
USHORT forum)                      /*   ...for this Forum                  */
{
     return(fdfarr[getdef(forum)->dfnum]->filnam);
}

static GBOOL                       /*   ok to use this new data file path? */
vfyndf(                            /* verify new data file path            */
USHORT forum,                      /*   Forum new data file path is for    */
CHAR *ndfil)                       /*   proposed new data file path        */
{
     CHAR olddfl[GCMAXPTH],newdfl[GCMAXPTH];

     normspec(newdfl,ndfil);
     normspec(olddfl,FORDEFN);
     if (sameas(olddfl,newdfl)) {
          deferr();
          return(FALSE);
     }
     normspec(olddfl,emldp);
     if (sameas(olddfl,newdfl)) {
          emlerr();
          return(FALSE);
     }
     normspec(olddfl,fdfarr[getdef(forum)->dfnum]->filnam);
     if (sameas(olddfl,newdfl)) {
          samerr();
          return(FALSE);
     }
     if (!fdfisopn(newdfl) && nfdf == maxfdf) {
          lmterr();
          return(FALSE);
     }
     return(TRUE);
}

static GBOOL                       /*   was it basically successful?       */
chgfdf(                            /* change a Forum's data file path      */
USHORT forum,                      /*   Forum new data file path is for    */
CHAR *ndfil)                       /*   proposed new data file path        */
{
     INT ndfnum;
     DFAFILE *oldbb,*newbb;
     struct fmidky fmkey;
     UINT reclen;
     struct msgdsk *recptr;

     if (!fdfisopn(ndfil)) {
          if (!fexist(ndfil)) {
               if (!creatfdf(ndfil)) {
                    return(FALSE);
               }
          }
     }
     ndfnum=opnfdf(ndfil);
     oldbb=fdfarr[getdef(forum)->dfnum];
     newbb=fdfarr[ndfnum];
     fmkey.forum=forum;
     fmkey.msgid=0L;
     dfaSetBlk(oldbb);
     if (dfaQueryGT(&fmkey,FFMKY)) {
          do {
               dfaAbsRec(NULL,FFMKY);
               reclen=dfaLastLen();
               recptr=(struct msgdsk *)oldbb->data;
               if (recptr->forum != forum) {
                    break;
               }
               dfaDelete();
               repmsg(recptr->msgid);
               dfaSetBlk(newbb);
               dfaInsertV(recptr,reclen);
               dfaRstBlk();
          } while (dfaQueryNX());
     }
     getdef(forum)->dfnum=ndfnum;
     updfors=TRUE;
     return(TRUE);
}

VOID
appgprept(VOID)                    /* application-specific GP info (stub)  */
{
}

VOID
appgprecd(VOID)                    /* application-specific GP record (stub)*/
{
}
