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

const char *SPIT_history[] =
{
"------------------------------------------------------------------",
"                                                                  ",
"                          SortShp v1.03                           ",
"                                                                  ",
"              by Gerry Shaw and FrANK G. Barchard, EAC            ",
"                                                                  ",
"                    Main program - Mar 25, 2004                   ",
"                                                                  ",
"------------------------------------------------------------------",
"                                                                  ",
" Version Date   SE History:                                       ",
" ------- ----   -- --------                                       ",
"    1.00 950218 FB Based on mergeshp                              ",
"    1.01 990312 FB Rewrite based on txt                           ",
"    1.02 020328 FB updated doc on file formats                    ",
"    1.03 040325 FB tolower does the names of shapes as well       ",
"                                                                  ",
"------------------------------------------------------------------",
"\0"
};

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

#include    <stdio.h>
#include    <string.h>
#include    <stdlib.h>
#include    "spit.h"

const char TextVersion[]="1.03 (Samba) 2007.12.4";
#define TOOL_VERSION 103
#define TOOL_NAME "sortshp"

int *OPTxlate;
int OPTxlatereverse;
int OPTnocr;
int OPTsortcase;
int OPTtolower;
int OPTbackwards;

#if 0
/*
;
; ABSTRACT
;
; sortshp - sort names in shape files
;
; SUMMARY
;
; sortshp -options <sourcefiles>
;   @file     response file, containing a list of options and files
;   =file     specify a output file ie sortshp source=dest
;   -v0       no console output
;   -v1       prints source file name and errors
;   -v2       status line for each file (default)
;   -w0       don't output file
;   -w1       output to standard out
;   -w2       output to file (default)
;   -w3       output to file and standard out
;   -w4       don't output file
;   -w5       hex output to standard out
;   -w6       hex output to file
;   -w7       hex output to file and standard out
;
; DESCRIPTION
;
; The sortshp tool sorts sorts the names in a shape file.  Only the
; table of contents is affected.  The shape data will still be in the
; original location.
; Works on any form of shape file
;
; RETURNS
;
; 0 - success
; n - number of files that failed
;
;
; SEE ALSO
;
; gx, Spit
;
; SAMPLE OUTPUT
;
; >gx vines.tga john.jpg =unsorted.fsh
; GX v5.06 (Neomythic) 020322 by Frank Barchard,EAC
; Reading Targa 'vines.tga'
; Writing PC Shape File 'unsorted.fsh'
; Reading Intel JPeg 'john.jpg'
;
; >sortshp unsorted.fsh =sorted.fsh
; unsorted.fsh: Reading, Sorting shape file 'unsorted.fsh'  Writing, done.
; total 1 files, 2 shapes
;
; >ginfo sorted.fsh
; GINFO v1.74 (Neo) 020304 by FrANK Barchard, EAC
; sorted.fsh:  PC Shape File, 2 frames
;  #0 'john': 256x256x888,            Position 0,0,     Size  196633,
;  #1 'vines':128x128x8888,           Position 0,0,     Size   65562,
; Bounding rectangle: (0,0..256,256) 256x256
;
; END ABSTRACT
;
*/
#endif


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

void SPIT_reset(void)
{
    OPTxlate = NULL;
    OPTxlatereverse = 0;
    OPTsortcase = 0;
    OPTnocr = 0;
    OPTtolower = 1;
    OPTbanner = 0;
    OPTbackwards = 0;
}

void SPIT_usage(const char *prgname, const char *envname, const char *urlname, int utype)
{
    printf("Sortshp v%s by FrANK Barchard, EAC\n",TextVersion);
    if (utype)
        printf("USAGE: %s -options [files]\n", prgname);

    switch (utype)
    {
        case 2:
            puts("    -i ignore case         -tolower lower case file names");
            puts("    -b backwards");
            puts("    -w write file                -v verbose");
            puts("    -r recurse subdirectories");
            puts("     @ response file              = output file");
          printf("type '%s -h' for more help\n", prgname);
          printf("type '%s -help' for web page (%s)\n", prgname, urlname);
            break;

        case 3:
            puts("");
          printf("VERSION: %s v%s, Spit v%.2f\n",SPIT_MACHINE,TextVersion,(float)SPIT_VERSION/100.0f);
            puts("SUMMARY: Sortshp sorts shapes by name within a shape file of any type");
          printf("         SPIT environment variable is %s\n",envname);
            puts("");
            puts("    @file     response file, containing a list of options and files");
          printf("    =file     specify a output file ie %s source=dest\n", prgname);
            puts("    -nologo   disable banner");
            puts("    -i0       case sensitive sort");
            puts("    -i        case insensitive sort");
            puts("    -tolower  lower case filenames");
            puts("    -r        recurse subdirectories");
            puts("    -v0       no console output");
            puts("    -v1       prints source file name and errors");
            puts("    -v2       status line for each file (default)");
            puts("    -v3       additional info");
            puts("    -w0       don't output file");
            puts("    -w1       output to standard out");
            puts("    -w2       output to file (default)");
            puts("    -w3       output to file and standard out");
            puts("    -w4       don't output file");
            puts("    -w5       hex output to standard out");
            puts("    -w6       hex output to file");
            puts("    -w7       hex output to file and standard out");

        default:
            break;
    }
}

char *SPIT_opt(const char *optptr)
{
    int i;
    char *d=(char *)0;
    char optbuf[SPITMAXLINE];

    for (i=0; (unsigned char)optptr[i]>(unsigned char)' '; ++i)
        optbuf[i] = (char)tolower(optptr[i]);
    optbuf[i] = 0;

    if (!d)
    {
        switch (*optptr|(char)' ')
        {
            case 'i':
                d = SPIT_getopt( &OPTsortcase,optptr+1, "info", 0, 1);
                break;

            case 'b':
                d = SPIT_getopt( &OPTbackwards,optptr+1, "backwards sort", 0, 1);
                break;

            case 't':
                if (!strnicmp(optptr, "tolower", 7))
                {
                    d = SPIT_getopt( &OPTtolower,optptr+7, "name to lower case", 0, 1);
                }
                break;

            case 'l':
            case 'n':
                d = SPIT_getopt( &OPTtolower,optptr+1, "name to lower case", 0, 1);
                break;

            default: ;
        }
    }
    return(d);
}

int main(int argc,char **argv)
{
    int more;
    int i;
    int j;
    int k;
    int fshnum;
    int numberofshapes = 0;
    SPITMEM infile;
    char destname[SPITMAXLINE];
    char statbuf[SPITMAXLINE];

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

        for (i=0; i<SPITargnum; ++i)
        {
            if (SPIT_loadfile(&infile, SPITsargv[i]))
            {
                strcpy(destname,SPITdargv[i]);
                if (!strchr(destname,'.'))
                {
                    strcat(destname,".fsh");
                }

                if (OPTtolower)
                    strlwr(destname);

                if (OPTverbose>=3)
                {
                    printf("Sorting shape file '%s' %s ",SPITsargv[i],OPTbackwards?"backwards":"");
                }

                fshnum = ggeti(infile.ptr+8,4);
                if (fshnum>=65536)
                    fshnum = ggetm(infile.ptr+8,4);

                numberofshapes += fshnum;

                for (j=0; j<fshnum; ++j)
                {
                    if (OPTtolower)
                    {
                        char *p = infile.ptr+16+j*8;
                        for (int l=0; l<4; ++l)
                        {
                            p[l] = tolower(p[l]);
                        }
                    }

                    for (k=0; k<fshnum-1; ++k)
                    {
                        int c;

                        if (OPTsortcase)
                            c = strnicmp(infile.ptr+16+k*8,infile.ptr+16+k*8+8,8);
                        else
                            c = strncmp(infile.ptr+16+k*8,infile.ptr+16+k*8+8,8);

                        if (OPTbackwards)
                            c = -c;

                        if (c>0)
                        {
                            memcpy(statbuf,infile.ptr+16+k*8,8);
                            memcpy(infile.ptr+16+k*8,infile.ptr+16+k*8+8,8);
                            memcpy(infile.ptr+16+k*8+8,statbuf,8);
                        }
                    }
                }
                SPIT_savefile(&infile, destname);

                if (OPTverbose>=3)
                {
                    printf("done.\n");
                }


                SPIT_free(&infile);
            }
        }
        if (OPTverbose>=3)
        {   printf("total %d files, %d shapes\n",SPITargnum,numberofshapes);
            SPIT_flush();
        }
        if (OPTverbose==1)
            puts("");
    } while (more > 0);
    SPIT_restore();

    return(0);
}

