/***************************************************************************
 *                                                                         *
 *   GALFMCVT.C                                                            *
 *                                                                         *
 *   Copyright (c) 1996-1997 Galacticomm, Inc.    All Rights Reserved.     *
 *                                                                         *
 *   Forum Message Conversion utility.                                     *
 *                                                                         *
 *                                           - J. Alvrus    7/1/96         *
 *                                                                         *
 ***************************************************************************/

#include "gcomm.h"
#include "excphand.h"
#include "gme.h"
#include "gmeutl.h"
#include "gmeloc.h"
#include "dfcapi.h"

_NOSCNS_                           /* keep DFCDISP.C happy                 */

#define FILFILE "galfmcvt.fil"     /* log file for files converted         */
#define FORFILE "galfmcvt.for"     /* log file for forums converted        */

struct cvtfil {                    /* converted file tracking record       */
     CHAR oldnam[GCMAXPTH];        /*   old data file name                 */
     CHAR newnam[GCMAXPTH];        /*   new data file name                 */
};

GBOOL keepflg=TRUE;                /* keep old data file                   */
GBOOL src20=TRUE;                  /* old data file in 2.0 format?         */
DFAFILE *defbb;                    /* forum definition data file           */
INT numcvt=0;                      /* number of files converted already    */
struct cvtfil *datlst=NULL;        /* array of converted data files        */
struct fordsk *defdat;             /* forum definition buffer              */

#undef inicvt
VOID fixname(CHAR *name);
VOID inicvt(VOID);
GBOOL didcvt(CHAR *datfil);
VOID addcvt(const CHAR *filnam);
VOID msgcvt(CHAR *datfil);

extern size_t cvtmsg(struct msgdsk *dst,VOID *src,size_t srclen,
                     INT srcflg,INT dstflg,GBOOL src20);

static VOID supFlags(CHAR *argv[],INT *srcflg,INT *dstflg);

INT srcflg=0,dstflg=0;             /* conversion flags                     */

INT
main(INT argc,CHAR *argv[])
{
     GBOOL fnd;
     USHORT len,fid;
     LONG pos;
     CHAR *cp,buf[128];
     FILE *fp;

TRY
     if ((fp=fopen(CVTCFGFIL,FOPRA)) != NULL) {
          fgets(buf,sizeof(buf),fp);    /* 1st line is old file directory */
          while (fgets(buf,sizeof(buf),fp) != NULL) {
               if (*(cp=buf+strlen(buf)-1) == '\n') {
                    *cp='\0';
               }
               if (sameas(buf,"GALFMCVT")) {
                    return(0);
               }
          }
          fclose(fp);
     }
     initvid();
     if (argc < REQNARG) {
          catastro("GALFMCVT: Incorrect number of arguments!");
     }
     dfcDspInit(NOSHOWIN);
#ifdef GCWINNT
     if (sameas(getUpdType(),"3.0 to NT")) {
          src20=FALSE;
     }
#endif
     if (argc > KEEPIDX && sameas(argv[KEEPIDX],"discard")) {
          keepflg=FALSE;
     }
     inicvt();
     fid=EMLID;
     if ((fp=fopen(FORFILE,FOPRA)) != NULL) {
          fgets(buf,sizeof(buf),fp);
          if (*(cp=buf+strlen(buf)-1) == '\n') {
               *cp='\0';
          }
          fid=(USHORT)atol(buf);
          fclose(fp);
     }
     defdat=(struct fordsk *)alcmem(fldoff(fordsk,info)+MAXFDV);
     defbb=dfaOpen("galfdef2.dat",fldoff(fordsk,info)+MAXFDV,NULL);
     supFlags(argv,&srcflg,&dstflg);
     for (fnd=dfaAcqGT(NULL,&fid,DIDKY) ; fnd ; fnd=dfaQueryNX()) {
          len=dfaLastLen();
          pos=dfaAbs();
          memmove(defdat,defbb->data,len);
          fixname(defdat->name);
          if (!didcvt(defdat->datfil)) {
               msgcvt(defdat->datfil);
          }
          dfaSetBlk(defbb);
          dfaGetAbs(NULL,pos,DIDKY);
          dfaUpdateV(defdat,len);
          if ((fp=fopen(FORFILE,FOPWA)) != NULL) {
               fprintf(fp,"%hu\n",defdat->forum);
               fclose(fp);
          }
     }
     if ((fp=fopen(CVTCFGFIL,FOPAA)) != NULL) {
          fprintf(fp,"GALFMCVT\n");
          fclose(fp);
          remove(FORFILE);
          remove(FILFILE);
     }
     dfcClrRecs();
     clsvid();
EXCEPT
     return(0);
}

VOID
fixname(                           /* get rid of any '/'s in forum name    */
CHAR *name)                        /*   buffer containing name to fix      */
{                                  /* (assumes defbb is current DFA file)  */
     CHAR cfl,buf[FORNSZ];
     size_t len;

     if (strchr(name,'/') != NULL) {
          stlcpy(buf,name,FORNSZ);
          if (buf[0] == '/') {
               memmove(buf,&buf[1],strlen(buf));
          }
          strrpl(buf,'/','_');
          cfl='0';
          while (dfaQueryEQ(buf,DNMKY)) {
               if ((len=strlen(buf)) >= FORNSZ-1) {
                    buf[FORNSZ-2]='\0';
                    len=FORNSZ-2;
               }
               buf[len]=cfl;
               buf[len+1]='\0';
               if (cfl++ > '9') {
                    catastro("Unable to fix the name of the %s forum,\n"
                             "too many other forums with similar names.",name);
               }
          }
          stlcpy(name,buf,FORNSZ);
     }
}

VOID
inicvt(VOID)                       /* initialize list of converted files   */
{
     INT i;
     CHAR *cp,buf[GCMAXPTH+1];
     FILE *fp;

     if ((fp=fopen(FILFILE,FOPRA)) != NULL) {
          i=0;
          while (fgets(buf,sizeof(buf),fp) != NULL) {
               if (*(cp=buf+strlen(buf)-1) == '\n') {
                    *cp='\0';
               }
               if ((++i)&1) {
                    addcvt(buf);
               }
               else {
                    stlcpy(datlst[numcvt++].newnam,buf,GCMAXPTH);
               }
          }
          fclose(fp);
          if ((i&1) && datlst != NULL) {
               numcvt=0;
               free(datlst);
               return;
          }
     }
}

GBOOL
didcvt(                            /* has this file been converted already?*/
CHAR *datfil)                      /*   data file (updated if already done)*/
{                                  /*   (also adds to list if not done)    */
     INT i;
     CHAR buf[GCMAXPTH];

     normspec(buf,datfil);
     for (i=0 ; i < numcvt ; ++i) {
          if (sameas(buf,datlst[i].oldnam)) {
               stlcpy(datfil,datlst[i].newnam,GCMAXPTH);
               return(TRUE);
          }
     }
     addcvt(buf);
     return(FALSE);
}

VOID
addcvt(                            /* add a file to list of converted      */
const CHAR *filnam)                /*   path and name of file to add       */
{
     if (numcvt == 0) {
          datlst=(struct cvtfil *)alcmem(sizeof(struct cvtfil));
     }
     else {
          datlst=(struct cvtfil *)alcrsz(datlst,numcvt*sizeof(struct cvtfil),
                                         (numcvt+1)*sizeof(struct cvtfil));
     }
     stlcpy(datlst[numcvt].oldnam,filnam,GCMAXPTH);
}

VOID
msgcvt(                            /* convert message data file            */
CHAR *datfil)                      /*   data file to convert (updated)     */
{
     size_t reclen;
     GBOOL fnd,renflg;
     LONG dfree,dneed;
     ULONG currec,totrec;
     CHAR *cp,dstpth[GCMAXPTH],dstnam[GCMAXFNM],srcnam[GCMAXFNM];
     DFAFILE *srcbb,*dstbb;
     FILE *fp;
     struct ffblk fb;

     if (sameas(datfil,"galfdf.dat")) {
          renflg=TRUE;
          strcpy(dstnam,strcpy(dstpth,"galfmsg2.dat"));
          strcpy(srcnam,datfil);
     }
     else {
          fileparts(GCPART_PATH,datfil,dstpth,GCMAXPTH);
          if (keepflg) {
               renflg=TRUE;
               fileparts(GCPART_FILE,datfil,dstnam,GCMAXFNM);
               dstnam[GCMAXFILE-1]='\0';
               stlcat(dstpth,dstnam,GCMAXPTH);
               cp=dstpth+strlen(dstpth);
               reclen=2;
               do {
                    *(cp+1)='\0';
                    *cp='0'+reclen++;
                    if (reclen > 9) {
                         normspec(dstpth,datfil);
                         fileparts(GCPART_PATH,dstpth,dstpth,GCMAXPTH);
                         catastro("Unable to create new forum message data file.\n"
                                  "Too many similarly named files in %s",dstpth);
                    }
                    stlcat(dstpth,".dat",GCMAXPTH);
               } while (isfile(dstpth));
               fileparts(GCPART_FNAM,datfil,srcnam,GCMAXFNM);
               fileparts(GCPART_FNAM,dstpth,dstnam,GCMAXFNM);
          }
          else {
               renflg=FALSE;
               strcpy(dstnam,fileparts(GCPART_FNAM,datfil,srcnam,GCMAXFNM));
               stlcat(dstpth,"$$$$temp.dat",GCMAXPTH);
          }
     }
     dfcDspFiles(strupr(srcnam),strupr(dstnam));
     dfree=dskfre(NULL);
     if (!fndfile(&fb,datfil,0)) {
          catastro("Forum message data file does not exist:\n%s",datfil);
     }
     dneed=fb.ff_fsize/1024;
     if (dfree < dneed) {
          catastro("Insufficient disk space to convert forum message\n"
                   "data file:  %s (%ld k free, %ld k required)",
                   datfil,dfree,dneed);
     }
     *(cp=&dstpth[strlen(dstpth)-4])='\0';
     if (!dfaVirgin("galfmsg2",dstpth)) {
          *cp='.';
          catastro("Unable to create new data file:\n%s",dstpth);
     }
     *cp='.';
     dfaMode(ACCLBV);
     dstbb=dfaOpen(dstpth,32798U,NULL);
     dfaMode(PRIMBV);
     srcbb=dfaOpen(datfil,32768U,NULL);
     currec=0L;
     totrec=dfaCountRec();
     for (fnd=dfaStepLO(NULL) ; fnd ; fnd=dfaStepNX(NULL)) {
          dfcDspRecs(++currec,totrec);
          if ((reclen=cvtmsg((struct msgdsk *)dstbb->data,srcbb->data,
                             dfaLastLen(),srcflg,dstflg,src20)) != 0) {
               dfaSetBlk(dstbb);
               dfaInsertV(NULL,reclen);
          }
          dfaSetBlk(srcbb);
     }
     dfaClose(srcbb);
     dfaClose(dstbb);
     if (!keepflg) {
          remove(datfil);
     }
     if (renflg) {
          stlcpy(datfil,dstpth,GCMAXPTH);
     }
     else if (rename(dstpth,datfil) != 0) {
          catastro("Unable to rename new data file\n%s to %s",
                   dstpth,datfil);
     }
     if ((fp=fopen(FILFILE,FOPAA)) != NULL) {
          fprintf(fp,"%s\n",datlst[numcvt].oldnam);
          fprintf(fp,"%s\n",datfil);
          fclose(fp);
     }
     stlcpy(datlst[numcvt].newnam,datfil,GCMAXPTH);
     if ((fp=fopen("galfmcvt.log",FOPAA)) != NULL) {
          fprintf(fp,"%s converted to %s (old file %s)\n",
                  datlst[numcvt].oldnam,datlst[numcvt].newnam,
                  (keepflg ? "kept" : "deleted"));
          fclose(fp);
     }
     ++numcvt;
}

static VOID
supFlags(                               /* set up conversion flags         */
CHAR *argv[],                           /*   cmd line parms                */
INT *srcflg,                            /*   source conversion flags       */
INT *dstflg)                            /*   dest conversion flags         */
{
     if (sameas(argv[SRCPKDIDX],NOTSPEC)) {
          dfaClose(srcbb);
          dfaClose(dstbb);
          catastro("GALFMCVT: Unable to perform conversion: "
                  "SourcePacked not specified!");
     }
     if (sameas(argv[SRCPKDIDX],"yes")) {
          *srcflg|=CVTPACKED;
     }
     if (sameas(argv[SRCBORDIDX],NOTSPEC)) {
          dfaClose(srcbb);
          dfaClose(dstbb);
          catastro("GALFMCVT: Unable to perform conversion: "
                  "SourceByteOrder not specified!");
     }
     if (sameas(argv[SRCBORDIDX],"big")) {
          *srcflg|=CVTBIGEND;
     }
     if (sameas(argv[DSTPKDIDX],NOTSPEC)) {
          dfaClose(srcbb);
          dfaClose(dstbb);
          catastro("GALFMCVT: Unable to perform conversion: "
                  "DestPacked not specified!");
     }
     if (sameas(argv[DSTPKDIDX],"yes")) {
          *dstflg|=CVTPACKED;
     }
     if (sameas(argv[DSTBORDIDX],NOTSPEC)) {
          dfaClose(srcbb);
          dfaClose(dstbb);
          catastro("GALFMCVT: Unable to perform conversion: "
                  "DestByteOrder not specified!");
     }
     if (sameas(argv[DSTBORDIDX],"big")) {
          *dstflg|=CVTBIGEND;
     }
}
