/***************************************************************************
 *                                                                         *
 *   BBSILANG.C                                                            *
 *                                                                         *
 *   Copyright (c) 1993-1997 Galacticomm, Inc.    All Rights Reserved      *
 *                                                                         *
 *   This program imports additional (or updated versions of) languages    *
 *   into the WGS .MSG files.  The source .MLX file will be imported into  *
 *   the .MSG file with the same root name in the current directory.       *
 *   The old .MSG file will be renamed to have the specified old           *
 *   extension.  The resulting .MSG file will have the structure of the    *
 *   old .MSG file, with the contents of the old messages saved wherever   *
 *   possible.  Any new language forms of any existing messages will       *
 *   be brought into the .MSG file from the .MLX file.                     *
 *                                                                         *
 *   The destination and source directories are always the default dir.    *
 *                                                                         *
 *   Usage:                                                                *
 *                                                                         *
 *        WGSILANG <file(s)-can be *> <old file extension>                 *
 *                                                                         *
 *                                            - C. Robert 1/31/93          *
 *                                                                         *
 *   Added "/o" flag as optional third parameter to overwrite all existing *
 *   text blocks.                                                          *
 *                                            - Bill Hyatt 7/10/93         *
 *                                                                         *
 ***************************************************************************/

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

#define FILREV "$Revision: 9 $"

#define MNMSIZ 9                   /* maximum size of each msg name (ditto)*/

extern
CHAR scntbl[][GVIDSCNSIZ]; /* linked in screens (c/o MAKESCNS)     */

CHAR *scnptr;                      /* pointer to "saved" screen buffer     */
INT nlingo=MAXLANG;                /* lingo.c stub of nlingo (fake-out)    */

INT dosx,dosy;                     /* saved DOS cursor position (for exit) */

FILE *oldfp,                       /* old message file block pointer       */
     *newfp,                       /* new message file block pointer       */
     *outfp;                       /* output message file block pointer    */

CHAR oldnam[80],                   /* old message file name                */
     newnam[80],                   /* new message file name                */
     newpth[80],                   /* new message file path prefix         */
     outnam[80];                   /* output message file name             */

INT msgcnt,                        /* messages counted so far              */
    numnew,                        /* number of messages in new msg file   */
    noldln,                        /* number of lingos in old msg file     */
    totlng,                        /* total number of languages in output  */
    impall;                        /* import all tblks, & overwrite old?   */

struct newmsgs {                   /* new message structure definition     */
     CHAR name[MNMSIZ];            /*   name of message                    */
     LONG offset;                  /*   offset to message in .MSG file     */
} *newmsg;                         /* array of MAXOPTS old message structs */

INT oldsal;                        /* saved salingo value for old .MSG file*/
struct altlng *oldlnm;             /* saved altlnm array for old .MSG file */

CHAR *lnglst[MAXLANG];             /* array of languages for output file   */
INT newmap[MAXLANG];               /* mapping of new languages to lnglst   */

struct msgent {                    /* message file linked-list entry       */
     struct msgent *link;          /*   forward ptr                        */
     CHAR name[13];                /*   file name including .msg & '\0'    */
} mshead,*mstptr=&mshead;          /* linked-list pointers for msg files   */

VOID fillist(struct ffblk *fb);
VOID import1(VOID);
VOID maktbl(VOID);
VOID setlnm(VOID);
VOID addnew(CHAR *nam,INT num);
VOID freeln(VOID);
VOID chkstf(VOID);
VOID opnwnd(VOID);
VOID clswnd(VOID);

INT
main(                              /* main program loop                    */
INT argc,                          /* number of command-line args          */
CHAR *argv[])                      /* array of command-line args           */
{
TRY
     INT i;
     CHAR fptmp[GCMAXFNM];
     struct ffblk fb;
     struct msgent *numsg;

#ifdef GCWINNT
     if (!canRunUtil()) {
          MessageBox(NULL,NOPROCEED,
                    argv[0],MB_ICONSTOP|MB_OK|MB_TASKMODAL|MB_SETFOREGROUND);
          return(1);
     }
#endif // GCWINNT
     initvid();
     if (argc < 3) {
          printf("WGSILANG -- Language Import/Update Utility\n");
          printf("Copyright (c) 1993-1997 Galacticomm, Inc.  All Rights "
                 "Reserved\n");
          printf("\n Command format is:\n");
          printf(" WGSILANG <file name or *> <extension for back-up> [/o]\n");
          printf("      /o: optional flag - if specified, ALL text blocks\n");
          printf("          will be imported, regardless whether a previous\n");
          printf("          version exists.\n");
          clsvid();
          return(1);
     }
     impall=(argc >= 4 && sameas(argv[3],"/o"));
     newmsg=(struct newmsgs *)alcmem(MAXOPTS*sizeof(struct newmsgs));
     inimsgrdr(OPTSIZE);
     oldlnm=(struct altlng *)alcmem(nlingo*sizeof(struct altlng));
     stzcpy(newpth,argv[1],sizeof(newpth));
     for (i=strlen(newpth)-1 ; i >= 0 ; i--) {
          if (newpth[i] == SL) {
               newpth[i+1]='\0';
               break;
          }
     }
     if (i == -1) {
          newpth[0]='\0';
     }
     if (strchr(argv[1],'.') != NULL) {
          stzcpy(newnam,argv[1],sizeof(newnam));
     }
     else {
          sprintf(newnam,"%s.mlx",argv[1]);
     }
     if (fnd1st(&fb,newnam,0)) {
          opnwnd();
          fillist(&fb);
          for (numsg=mshead.link ; numsg != NULL ; numsg=numsg->link) {
               strcpy(newnam,newpth);
               strncat(newnam,numsg->name,sizeof(newnam));
               sprintf(outnam,"%s.msg",
                       fileparts(GCPART_FILE,numsg->name,fptmp,GCMAXFNM));
               strupr(newnam);
               strupr(outnam);
               if (isfile(outnam)) {
                    sprintf(oldnam,"%s.%s",fptmp,argv[2]);
                    strupr(oldnam);
                    printf("\n Importing %s into %s...",newnam,outnam);
                    import1();
               }
          }
          clswnd();
     }
     else {
          printf("WGSILANG: No match for \"%s\" found!\n",newnam);
     }
     return(0);
EXCEPT
#ifdef GCWINNT
     return(1);
#endif // GCWINNT
}

VOID
fillist(                           /* gen in-memory linked list of files   */
struct ffblk *fb)                      /* fb to use (returned from fnd1st)*/
{
     struct msgent *numsg;

     mshead.link=NULL;
     mstptr=&mshead;
     do {
          numsg=(struct msgent *)alcmem(sizeof(struct msgent));
          numsg->link=NULL;
          strcpy(numsg->name,fb->ff_name);
          mstptr->link=numsg;
          mstptr=numsg;
     } while (fndnxt(fb));
}

VOID
import1(VOID)                      /* merge newnam and oldnam into outnam  */
{
     LONG fpos;
     INT i,map,ncma;

     if ((newfp=fopen(newnam,FOPRB)) == NULL) {
          clswnd();
          printf("WGSILANG: Can't open %s for input, exiting...\n",newnam);
          exit(1);
     }
     if ((oldfp=fopen(oldnam,FOPRB)) == NULL) {
          if (rename(outnam,oldnam)) {
               clswnd();
               printf("WGSILANG: Error in renaming %s to %s, exiting...\n",
                    outnam,oldnam);
               exit(1);
          }
          if ((oldfp=fopen(oldnam,FOPRB)) == NULL) {
               clswnd();
               printf("WGSILANG: Can't open %s for input, exiting...\n",oldnam);
               exit(1);
          }
     }
     if ((outfp=fopen(outnam,FOPWB)) == NULL) {
          clswnd();
          printf("WGSILANG: Can't open %s for output, exiting...\n",outnam);
          exit(1);
     }
     maktbl();
     msgcnt=0;
     rdfp=oldfp;
     while (rdmsg()) {
          chkstf();
          scanalt();
          litopts();
          if (msgcnt == 0) {
               if (sameas(msgnam,"LANGUAGE")
             || sameas(newmsg[0].name,"LANGUAGE")) {
                    fprintf(outfp,"\r\nLANGUAGE {");
                    for (i=0 ; i < totlng ; i++) {
                         if (i != 0) {
                              fprintf(outfp,",{");
                         }
                         fprintf(outfp,"%s}",lnglst[i]);
                    }
                    fprintf(outfp,STR_EOL STR_EOL);
               }
          }
          if (sameas(msgnam,"LANGUAGE")) {
               if (msgcnt != 0) {
                    catastro("In %s, LANGUAGE{} must be the very first option",
                             oldnam);
               }
          }
          else {
               fprintf(outfp,"%s\r\n%s {",hlpbuf,msgnam);
               setlnm();
               fpos=ftell(oldfp);
               ncma=0;
               for (i=0 ; i < totlng ; i++) {
                    if (!impall) {
                         if (i < oldsal && oldlnm[i].value.fsk != 0L) {
                              while (ncma != 0) {
                                   fprintf(outfp,",");
                                   ncma--;
                              }
                              if (i != 0) {
                                   fprintf(outfp,",{");
                              }
                              loadtv(oldfp,&oldlnm[i]);
                              putval(outfp);
                              fprintf(outfp,"}");
                         }
                         else if ((map=newmap[i]) != -1 && map < salingo
                      && altlnm[map].value.fsk != 0L) {
                              while (ncma != 0) {
                                   fprintf(outfp,",");
                                   ncma--;
                              }
                              if (i != 0) {
                                   fprintf(outfp,",{");
                              }
                              loadtv(newfp,&altlnm[map]);
                              putval(outfp);
                              fprintf(outfp,"}");
                         }
                         else {
                              if (i == 0) {
                                   fprintf(outfp,"}");
                              }
                              else {
                                   ncma++;
                              }
                         }
                    }
                    else {
                         if ((map=newmap[i]) != -1 && map < salingo
                             && altlnm[map].value.fsk != 0L) {
                              while (ncma != 0) {
                                   fprintf(outfp,",");
                                   ncma--;
                              }
                              if (i != 0) {
                                   fprintf(outfp,",{");
                              }
                              loadtv(newfp,&altlnm[map]);
                              putval(outfp);
                              fprintf(outfp,"}");
                         }
                         else if (i < oldsal && oldlnm[i].value.fsk != 0L) {
                              while (ncma != 0) {
                                   fprintf(outfp,",");
                                   ncma--;
                              }
                              if (i != 0) {
                                   fprintf(outfp,",{");
                              }
                              loadtv(oldfp,&oldlnm[i]);
                              putval(outfp);
                              fprintf(outfp,"}");
                         }
                         else {
                              if (i == 0) {
                                   fprintf(outfp,"}");
                              }
                              else {
                                   ncma++;
                              }
                         }
                    }
               }
               fprintf(outfp,"%s"STR_EOL STR_EOL,lobuf);
               fseek(oldfp,fpos,SEEK_SET);
          }
          msgcnt++;
     }
     fclose(oldfp);
     fclose(newfp);
     fclose(outfp);
     freeln();
}

VOID
maktbl(VOID)                       /* fill in the newmsg array with info   */
{
     INT i;

     rdfp=oldfp;
     if (rdmsg()) {
          scanalt();
          if (sameas(msgnam,"LANGUAGE")) {
               if ((noldln=salingo) > MAXLANG) {
                    catastro("Too many languages in %s!",oldnam);
               }
               for (i=0 ; i < noldln ; i++) {
                    if (altlnm[i].value.fsk == 0L) {
                         catastro("Language name #%d omitted in %s",i,oldnam);
                    }
                    if (i != 0) {
                         loadtv(oldfp,&altlnm[i]);
                    }
                    lnglst[i]=alcdup(txtbuf);
               }
          }
          else {
               noldln=1;
               lnglst[0]=alcdup(DFTLNG);
          }
          totlng=noldln;
     }
     else {
          totlng=noldln=1;
          lnglst[0]=alcdup(DFTLNG);
     }
     rewind(oldfp);
     setmem(newmap,sizeof(newmap),0xFF);
     setmem(newmsg,MAXOPTS*sizeof(struct newmsgs),0);
     msgcnt=0;
     rdfp=newfp;
     while (rdmsg()) {
          scanalt();
          chkstf();
          if (sameas(msgnam,"LANGUAGE")) {
               if (msgcnt != 0) {
                    catastro("In %s, LANGUAGE{} must be the very first option",
                             newnam);
               }
               for (i=0 ; i < salingo ; i++) {
                    if (altlnm[i].value.fsk == 0L) {
                         catastro("Language name #%d omitted in %s",i,
                                  newnam);
                    }
                    if (i != 0) {
                         loadtv(newfp,&altlnm[i]);
                    }
                    addnew(txtbuf,i);
               }
          }
          else if (msgcnt == 0) {
               newmap[0]=0;
          }
          strcpy(newmsg[msgcnt].name,msgnam);
          newmsg[msgcnt].offset=altlnm[0].value.fsk;
          msgcnt++;
     }
     numnew=msgcnt;
}

VOID
setlnm(VOID)                       /* set oldlnm and altlnm appropriately  */
{
     INT i;

     oldsal=salingo;
     movmem(altlnm,oldlnm,oldsal*sizeof(struct altlng));
     for (i=0 ; i < numnew ; i++) {
          if (sameas(newmsg[i].name,msgnam)) {
               rdfp=newfp;
               fseek(newfp,newmsg[i].offset,SEEK_SET);
               getval(newfp);
               scanalt();
               altlnm[0].value.fsk=newmsg[i].offset;
               rdfp=oldfp;
               return;
          }
     }
     salingo=0;
}

VOID
addnew(                            /* possibly add new language to list    */
CHAR *nam,
INT num)
{
     INT i;

     for (i=0 ; i < noldln ; i++) {
          if (sameas(lnglst[i],nam)) {
               newmap[i]=num;
               return;
          }
     }
     if (totlng == MAXLANG-1) {
          catastro("Too many languages to import from %s!",newnam);
     }
     lnglst[totlng]=alcdup(nam);
     newmap[totlng]=num;
     totlng++;
}

VOID
freeln(VOID)                       /* free memory used for languages       */
{
     INT i;

     for (i=0 ; i < totlng ; i++) {
          free(lnglst[i]);
     }
}

VOID
chkstf(VOID)                       /* check to make sure everything's ok   */
{
     if (msgcnt == MAXOPTS-1) {
          clswnd();
          printf("WGSILANG: Count exceeded at %s, exiting...\n",msgnam);
          exit(1);
     }
}

VOID
opnwnd(VOID)                       /* open up the WGSILANG work window     */
{
     dosx=curcurx();
     dosy=curcury();
     scn2mem(scnptr=alcmem(GVIDSCNSIZ),0,GVIDSCNSIZ);
     explodeto(cvtscn(scntbl[0]),0,0,70,10,1,7);
     proff(0,0);
     setwin(NULL,2,10,69,16,1);
     setatr(0x1F);
     locate(2,9);
     cursiz(GVIDNOCURS);
}

VOID
clswnd(VOID)                       /* close up the WGSILANG work window    */
{
     mem2scn(scnptr,0,GVIDSCNSIZ);
     setwin(NULL,0,0,79,24,1);
     free(scnptr);
     locate(dosx,dosy);
     cursiz(GVIDLILCURS);
     setatr(0x07);
     clsvid();
}
