// (c) 1991-2007 Electronic Arts Inc.

const char *SPIT_history[] =
{
"------------------------------------------------------------------",
"                                                                  ",
"                                                                  ",
"                          hhmerge v1.00                           ",
" Merges HHC or HHK (HTML Help Contents/Index) files.              ",
"                                                                  ",
"                      by Kenney Wong, EAC                         ",
"                                                                  ",
"                   Main program - July 14, 1999                   ",
"                                                                  ",
"------------------------------------------------------------------",
"                                                                  ",
" Version Date   SE History:                                       ",
" ------- ----   -- --------                                       ",
" 1.00    990714 KW Created - minimal error checking               ",
" 1.01    990830 KW inserts second file into first file at tagname ",
"                                                                  ",
"------------------------------------------------------------------",
"\0"
};


/****************************************************************/
/*  Spit Setup                                                  */
/****************************************************************/

#include "spit.h"
#include "stdgimex.h"

const char TextVersion[]="1.01 (Samba) 2007.12.4";
#define TOOL_VERSION 101
#define TOOL_NAME "hhmerge"

struct SPITMEM *infiles;
struct SPITMEM  outfile;

char OPTtagname[80];

/*
;
; UNABSTRACT
;
; hhmerge - Merges HHC or HHK (HTML Help Contents/Index) files
;
; SUMMARY
;
; hhmerge -options files -=outputfile
;     default     appends files together
;     -t<tagname> inserts second file into first file at <tagname>
;
; DESCRIPTION
;
; Takes HHC (HTML Help Contents) or HHK (HTML Help Index) files
; and merges them into one.
;
; SAMPLE OUTPUT
;
; Concatenates help1.hhc and help2.hhc:
;     hhmerge help1.hhc help2.hhc -=helpmerged.hhc
;
; Inserts help2.hhc into help1.hhc where label "Miscellaneous" is found:
;     hhmerge -tMiscellaneous help1.hhc help2.hhc -=helpmerged.hhc
;
; END ABSTRACT
;
*/

/****************************************************************/
/*  SPIT Routines                                               */
/****************************************************************/

void SPIT_reset(void)
{
    OPTtagname[0] = '\0';

    return;
}

void SPIT_usage(const char *prgname, const char *envname, const char *urlname, int utype)
{
    printf("hhmerge v%s by Kenney Wong\n",TextVersion);

    if (utype)
        printf("USAGE: %s -options files -=outputfile\n", prgname);

    switch (utype)
    {
        case 0:
        case 1:
            break;

        case 2:
            puts("SUMMARY: hhmerge - Merges HHC or HHK (HTML Help Contents/Index) files");
            puts("SUMMARY: -h for additional help");
            break;

        case 3:
            puts("");
          printf("VERSION: %s v%s, Spit v%.2f\n",SPIT_MACHINE,TextVersion,(float)SPIT_VERSION/100.0f);
            puts("SUMMARY: hhmerge - Merges HHC or HHK (HTML Help Contents/Index) files");
            puts("");
            puts("    -=file      output file");
            puts("    -t<tagname> inserts all other files into first file at <tagname>");
            puts("");
            puts("EXAMPLE:");
            puts("");
            puts("Concatenates help1.hhc and help2.hhc:");
            puts("  hhmerge help1.hhc help2.hhc -=helpmerged.hhc");
            puts("");
            puts("Inserts help2.hhc into help1.hhc where label \"Miscellaneous\" is found:");
            puts("  hhmerge -tMiscellaneous help1.hhc help2.hhc -=helpmerged.hhc");
            puts("");
            break;

        default:
            break;
    }
}

char *SPIT_opt(const char* optptr)
{
    const char *s;
    char optchar;

    s = optptr;
    optchar = (char) (*s++|(char)' ');
    switch (optchar)
    {
        case 't':
            s = SPIT_getstropt(OPTtagname,s,"tag name","",SPITYES,80);
            break;

        default:
            s = 0;
    }
    return((char *)s);
}

/* like strstr, searches for substring in source string, but terminates at newline. */
char *strstrn(char *src, char *substr)
{
    char *startsrcptr=src;
    char *srcptr;
    char *substrptr;

    while(*startsrcptr && *startsrcptr!='\n')
    {
        srcptr=startsrcptr;
        substrptr=substr;
        while(*substrptr && *srcptr && *srcptr!='\n' && *substrptr==*srcptr)
        {
            substrptr++;
            srcptr++;
        }
        /* is match? */
        if(!*substrptr)
            return(startsrcptr);
        startsrcptr++;
    }

    return((char *)0);
}

/* search backwards for first occurence of string within buffer string from specified position
   returns pointer to string, null if not found
*/
char *strstrreverse(char *buf, char *startpos, char *searchstr)
{
    char *foundpos;

    while(startpos>buf)
    {
        --startpos;
        while(startpos>buf && *startpos!='\n') --startpos;  // rewind to previous line
        foundpos = strstrn(startpos+1,searchstr);
        if(foundpos) return(foundpos);
    }

    return((char*)0);
}

int loadfiles()
{
    int i;
    int ok=1;

    /* get memory for each file */
    infiles = (struct SPITMEM *)galloc(sizeof(struct SPITMEM)*SPITargnum);
    for (i=0; i<SPITargnum; ++i)
    {
        if (!SPIT_loadfile(&infiles[i], SPITsargv[i]))
        {
            ok=0;
            i=SPITargnum;
        }
    }
    /*
    if (!SPIT_loadfilev(&outfile, SPITdargv[0]))
    {
        ok=0;
    }
    */

    return(ok);
}

void freefiles()
{
    int i;

    for (i=0; i<SPITargnum; ++i)
    {
        if(&infiles[i])
            SPIT_free(&infiles[i]);
    }
    /*
    if(&outfile)
        SPIT_free(&outfiles);
    */
}

void appendhhfiles()
{
    int i,copysize=0,allsize=0;
    char *inpos;

    if(!loadfiles())    /* could not load all files... free up memory */
    {
        freefiles();
        printf("ERROR: Could not load files.\n");
        return;
    }

    /* find total size of all files */
    for (i=0; i<SPITargnum; ++i)
        allsize += infiles[i].len;

    if(SPIT_alloc(&outfile, allsize))
    {
        /* seek to end of last item */
        infiles[0].ptr[infiles[0].len] = '\0';
        inpos = strstrreverse(infiles[0].ptr,infiles[0].ptr+infiles[0].len,"</UL>");  /* search backwards for </UL> tag */
        outfile.len = 0;

        if(inpos)
        {
            /* copy up to tag */
            copysize = (int)(inpos-infiles[0].ptr);
            memcpy(outfile.ptr,infiles[0].ptr,copysize);
            outfile.len += copysize;
        }

        if(copysize)
        {
            /* copy next file */
            copysize = infiles[1].len;
            memcpy(outfile.ptr+outfile.len,infiles[1].ptr,copysize);
            outfile.len += copysize;

            /* copy remainder of first file */
            copysize = infiles[0].len-(int)(inpos-infiles[0].ptr);
            memcpy(outfile.ptr+outfile.len,inpos,copysize);
            outfile.len += copysize;
        }

        SPIT_flush();
        SPIT_savefile(&outfile, SPITdargv[0]);
        SPIT_free(&outfile);
    }
    freefiles();
}

void inserthhfiles()
{
    int i,copysize=0,allsize=0;
    char *tagpos,*objstart,*objend;
    char tagname[80];

    if(!loadfiles())    /* could not load all files... free up memory */
    {
        freefiles();
        printf("ERROR: Could not load files.\n");
        return;
    }

    /* find total size of all files */
    for (i=0; i<SPITargnum; ++i)
        allsize += infiles[i].len;

    if(SPIT_alloc(&outfile, allsize))
    {
        outfile.len = 0;
        strcpy(tagname,"\"");
        strcat(tagname,OPTtagname);
        strcat(tagname,"\"");

        /* look for insert item */
        infiles[0].ptr[infiles[0].len] = '\0';
        tagpos = strstr(infiles[0].ptr,tagname);  /* search for user-defined tag */
        if(!tagpos)
        {
            printf("ERROR: Could not find tag \"%s\"",tagname);
            freefiles();
            return;
        }

        /* search backwards for <LI> tag */
        objstart = strstrreverse(infiles[0].ptr,tagpos,"<LI>");
        if(!objstart)
        {
            printf("ERROR: Could not find <LI> tag.");
            freefiles();
            return;
        }

        /* search for </OBJECT> tag */
        objend = strstr(objstart,"</OBJECT>");
        if(!objend)
        {
            printf("ERROR: Could not find </OBJECT> tag.");
            freefiles();
            return;
        }
        objend += strlen("</OBJECT>");

        /* copy up to object start */
        copysize = (int)(objstart-infiles[0].ptr);
        memcpy(outfile.ptr,infiles[0].ptr,copysize);
        outfile.len += copysize;

        if(copysize)
        {
            /* copy next file */
            copysize = infiles[1].len;
            memcpy(outfile.ptr+outfile.len,infiles[1].ptr,copysize);
            outfile.len += copysize;

            /* copy remainder of first file */
            copysize = (int)(infiles[0].ptr+infiles[0].len-objend);
            memcpy(outfile.ptr+outfile.len,objend,copysize);
            outfile.len += copysize;
        }

        SPIT_flush();
        SPIT_savefile(&outfile, SPITdargv[0]);
        SPIT_free(&outfile);
    }
    freefiles();
}

int main(int argc, char* argv[])
{
    int more;
    int err=0;

    SPIT_init(SPIT_reset, SPIT_usage, SPIT_opt, SPIT_history);
    do
    {
        more = SPIT_parse(argc, argv, TOOL_NAME, TOOL_VERSION);
    } while (more>0);

    if (!SPIThelpgiven)
    {
        /* ensure at least 2 source files */
        if (!err && SPITargnum<2)
        {
            printf("ERROR: At least 2 source files must be specified for merge.\n");
            err = 1;
        }

        /* ensure exactly 1 output file */
        /* TODO... */
        if (!err)
        {
        }

        /* ensure all files are of same type */
        /* TODO... */
        if (!err)
        {
        }

        /* merge files */
        if (!err)
        {
            if(!OPTtagname[0])
                appendhhfiles();
            else
                inserthhfiles();
        }
    }

    SPIT_restore();

    if (galloccount)
        printf("galloccount = %i\n", galloccount);

    return(0);
}

