/*****************************************************************************
 * $Id$
 *
 * This module has a number of additions and improvements over the original
 * implementation to be suitable for usage in GDAL HDF driver.
 *
 * Andrey Kiselev <dron@ak4719.spb.edu> is responsible for all the changes.
 ****************************************************************************/

/*
Copyright (C) 1996 Hughes and Applied Research Corporation

Permission to use, modify, and distribute this software and its documentation 
for any purpose without fee is hereby granted, provided that the above 
copyright notice appear in all copies and that both that copyright notice and 
this permission notice appear in supporting documentation.
*/
/*****************************************************************************
REVISIONS:

Aug 31, 1999  Abe Taaheri    Changed memory allocation for utility strings to
                             the size of UTLSTR_MAX_SIZE.
			     Added error check for memory unavailability in
			     several functions.
			     Added check for NULL metabuf returned from
			     EHmeta... functions. NULL pointer returned from
			     EHmeta... functions indicate that memory could not
			     be allocated for metabuf.

June 05, 2003 Abe Taaheri / Bruce Beaumont

                            Changed MAXNREGIONS to 1024 to support MOPITT data
			    Supplied cast for compcode in call to 
			      SDsetcompress to avoid compiler error
			    Removed declaration for unused variable rstatus 
			      in SWwrrdfield
			    Removed initialization code for unused variables 
			      in SWwrrdfield
			    Removed declaration for unused variable tmpVal 
			      in SWdefboxregion
			    Added code in SWdefboxregion to check for l_index k
			      exceeding NSWATHREGN to avoid overwriting 
			      memory
			    Removed declaration for unused variable retchar 
			      in SWregionl_index
			    Removed initialization code for unused variables 
			      in SWregionl_index
			    Removed declarations for unused variables tstatus,
			      nfields, nflgs, and swathname in SWextractregion
			    Removed initialization code for unused variables 
			      in SWextractregion
			    Removed declaration for unused variable 
			      land_status in SWscan2longlat
			    Removed initialization code for unused variables 
			      in SWscan2longlat
			    Added clear (0) of timeflag in SWextractperiod if 
			      return status from SWextractregion is non-zero
			    Removed declarations for unused variables tstatus,
			      scandim, ndfields, ndflds, and swathname in 
			      SWregioninfo
			    Removed initialization code for unused variables 
			      in SWregioninfo
			    Added clear (0) of timeflag in SWperiodinfo if 
			      return status from SWregioninfo is non-zero
			    Removed declarations for unused variables size, 
			      nfields, nflds, nswath, idxsz, cornerlon, and 
			      cornerlat in SWdefscanregion
			    Removed initialization code for unused variables 
			      in SWdefscanregion
			    Removed declarations for unused variables dims2, 
			      rank, nt, swathname, dimlist, and buffer in 
			      SWupdateidxmap
			    Removed declaration for unused variable statmeta 
			      in SWgeomapinfo
******************************************************************************/

#include "cpl_port.h" /* for M_PI */
#include "cpl_string.h" /* for CPLsnprintf */

#include "mfhdf.h"
#include "hcomp.h"
#include "HdfEosDef.h"
#include <math.h>

#include "hdf4compat.h"

#define SWIDOFFSET 1048576


static int32 SWX1dcomb[512*3];
static int32 SWXSDcomb[512*5];
static char  SWXSDname[HDFE_NAMBUFSIZE];
static char  SWXSDdims[HDFE_DIMBUFSIZE];

/* This flag was added to allow the Time field to have different Dimensions
** than Longitude and Latitude and still be used for subsetting
** 23 June,1997  DaW
*/
static intn  timeflag = 0;


/* Added for routine that converts scanline to Lat/long
** for floating scene subsetting
** Jul 1999 DaW
*/
#define RADOE	6371.0		/* Radius of Earth in Km */

#define NSWATH 200
/* Swath Structure External Arrays */
struct swathStructure 
{
    int32 active;
    int32 IDTable;
    int32 VIDTable[3];
    int32 fid;
    int32 nSDS;
    int32 *sdsID;
    int32 compcode;
    intn  compparm[5];
    int32 tilecode;
    int32 tilerank;
    int32 tiledims[8];
};
static struct swathStructure SWXSwath[NSWATH];



#define NSWATHREGN 256
#define MAXNREGIONS 1024
struct swathRegion
{
    int32 fid;
    int32 swathID;
    int32 nRegions;
    int32 StartRegion[MAXNREGIONS];
    int32 StopRegion[MAXNREGIONS];
    int32 StartVertical[8];
    int32 StopVertical[8];
    int32 StartScan[8];
    int32 StopScan[8];
    char *DimNamePtr[8];
    intn band8flag;
    intn  scanflag;
};
static struct swathRegion *SWXRegion[NSWATHREGN];

/* define a macro for the string size of the utility strings. The value
   of 80 in previous version of this code was resulting in core dump (Array 
   Bounds Write and Array Bounds Read problem in SWfinfo function and the 
   functions called from there) for 7-8 dimensional fields where the 
   string length for "DimList" can exceed 80 characters, including " and 
   commas in the string. The length now is 512 which seems to be more 
   than enough to avoid the problem mentioned above. */
   
#define UTLSTR_MAX_SIZE 512

/* Swath Prototypes (internal routines) */
static intn SWchkswid(int32, const char *, int32 *, int32 *, int32 *);
static int32 SWfinfo(int32, const char *, const char *, int32 *,
                     int32 [], int32 *, char *);
static intn SWdefinefield(int32, const char *, const char *, const char *, int32, int32);
static intn SWwrrdattr(int32, const char *, int32, int32, const char *, VOIDP);
static intn SW1dfldsrch(int32, int32, const char *, const char *, int32 *,
                        int32 *, int32 *);
static intn SWSDfldsrch(int32, int32, const char *, int32 *, int32 *, 
                        int32 *, int32 *, int32 [], int32 *);
static intn SWwrrdfield(int32, const char *, const char *,
                        int32 [], int32 [], int32 [], VOIDP);
static int32 SWinqfields(int32, const char *, char *, int32 [], int32 []);
static intn SWscan2longlat(int32, const char *, VOIDP, int32 [], int32 [],
                           int32 *, int32, int32);


/*----------------------------------------------------------------------------|
|  BEGIN_PROLOG                                                               |
|                                                                             |
|  FUNCTION: SWopen                                                           |
|                                                                             |
|  DESCRIPTION:                                                               |
|                                                                             |
|                                                                             |
|  Return Value    Type     Units     Description                             |
|  ============   ======  =========   =====================================   |
|  fid            int32               HDF-EOS file ID                         |
|                                                                             |
|  INPUTS:                                                                    |
|  filename       char                Filename                                |
|  access         intn                HDF access code                         |
|                                                                             |
|                                                                             |
|  OUTPUTS:                                                                   |
|             None                                                            |
|                                                                             |
|  NOTES:                                                                     |
|                                                                             |
|                                                                             |
|   Date     Programmer   Description                                         |
|  ======   ============  =================================================   |
|  Jun 96   Joel Gales    Original Programmer                                 |
|                                                                             |
|  END_PROLOG                                                                 |
-----------------------------------------------------------------------------*/
int32
SWopen(const char *filename, intn i_access)

{
    int32           fid /* HDF-EOS file ID */ ;

    /* Call EHopen to perform file access */
    /* ---------------------------------- */
    fid = EHopen(filename, i_access);

    return (fid);
}

/*----------------------------------------------------------------------------|
|  BEGIN_PROLOG                                                               |
|                                                                             |
|  FUNCTION: SWcreate                                                         |
|                                                                             |
|  DESCRIPTION: Creates a new swath structure and returns swath ID            |
|                                                                             |
|                                                                             |
|  Return Value    Type     Units     Description                             |
|  ============   ======  =========   =====================================   |
|  swathID        int32               Swath structure ID                      |
|                                                                             |
|  INPUTS:                                                                    |
|  fid            int32               File ID                                 |
|  swathname      char                Swath structure name                    |
|                                                                             |
|  OUTPUTS:                                                                   |
|             None                                                            |
|                                                                             |
|  NOTES:                                                                     |
|                                                                             |
|                                                                             |
|   Date     Programmer   Description                                         |
|  ======   ============  =================================================   |
|  Jun 96   Joel Gales    Original Programmer                                 |
|  Aug 96   Joel Gales    Make metadata ODL compliant                         |
|  Sep 96   Joel Gales    Check swath name for length                         |
|  Mar 97   Joel Gales    Enlarge utlbuf to 512                               |
|                                                                             |
|  END_PROLOG                                                                 |
-----------------------------------------------------------------------------*/
int32
SWcreate(int32 fid, const char *swathname)
{
    intn            i;		/* Loop index */
    intn            nswathopen = 0;	/* # of swath structures open */
    intn            status = 0;	/* routine return status variable */

    uint8           l_access;	/* Read/Write file access code */

    int32           HDFfid;	/* HDF file id */
    int32           vgRef;	/* Vgroup reference number */
    int32           vgid[4];	/* Vgroup ID array */
    int32           swathID = -1;	/* HDF-EOS swath ID */

    int32           sdInterfaceID;	/* HDF SDS interface ID */
    int32           idOffset = SWIDOFFSET;	/* Swath ID offset */
    int32           nSwath = 0;	/* Swath counter */

    char            name[80];	/* Vgroup name */
    char            class[80];	/* Vgroup class */
    char            errbuf[256];/* Buffer for error message */
    char            utlbuf[512];/* Utility buffer */
    char            utlbuf2[32];/* Utility buffer 2 */

    /*
     * Check HDF-EOS file ID, get back HDF file ID, SD interface ID  and
     * access code
     */
    status = EHchkfid(fid, swathname, &HDFfid, &sdInterfaceID, &l_access);


    /* Check swathname for length */
    /* -------------------------- */
    if ((intn) strlen(swathname) > VGNAMELENMAX)
    {
	status = -1;
	HEpush(DFE_GENAPP, "SWcreate", __FILE__, __LINE__);
	HEreport("Swathname \"%s\" must be less than %d characters.\n",
		 swathname, VGNAMELENMAX);
    }


    if (status == 0)
    {

	/* Determine number of swaths currently opened */
	/* ------------------------------------------- */
	for (i = 0; i < NSWATH; i++)
	{
	    nswathopen += SWXSwath[i].active;
	}


	/* Setup file interface */
	/* -------------------- */
	if (nswathopen < NSWATH)
	{

	    /* Check that swath has not been previously opened */
	    /* ----------------------------------------------- */
	    vgRef = -1;

	    while (1)
	    {
		vgRef = Vgetid(HDFfid, vgRef);

		/* If no more Vgroups then exist while loop */
		/* ---------------------------------------- */
		if (vgRef == -1)
		{
		    break;
		}

		/* Get name and class of Vgroup */
		/* ---------------------------- */
		vgid[0] = Vattach(HDFfid, vgRef, "r");
		Vgetname(vgid[0], name);
		Vgetclass(vgid[0], class);
		Vdetach(vgid[0]);

		/* If SWATH then increment # swath counter */
		/* --------------------------------------- */
		if (strcmp(class, "SWATH") == 0)
		{
		    nSwath++;
		}

		/* If swath already exist, return error */
		/* ------------------------------------ */
		if (strcmp(name, swathname) == 0 &&
		    strcmp(class, "SWATH") == 0)
		{
		    status = -1;
		    HEpush(DFE_GENAPP, "SWcreate", __FILE__, __LINE__);
		    HEreport("\"%s\" already exists.\n", swathname);
		    break;
		}
	    }


	    if (status == 0)
	    {

		/* Create Root Vgroup for Swath */
		/* ---------------------------- */
		vgid[0] = Vattach(HDFfid, -1, "w");


		/* Set Name and Class (SWATH) */
		/* -------------------------- */
		Vsetname(vgid[0], swathname);
		Vsetclass(vgid[0], "SWATH");



		/* Create Geolocation Fields Vgroup */
		/* -------------------------------- */
		vgid[1] = Vattach(HDFfid, -1, "w");
		Vsetname(vgid[1], "Geolocation Fields");
		Vsetclass(vgid[1], "SWATH Vgroup");
		Vinsert(vgid[0], vgid[1]);



		/* Create Data Fields Vgroup */
		/* ------------------------- */
		vgid[2] = Vattach(HDFfid, -1, "w");
		Vsetname(vgid[2], "Data Fields");
		Vsetclass(vgid[2], "SWATH Vgroup");
		Vinsert(vgid[0], vgid[2]);



		/* Create Attributes Vgroup */
		/* ------------------------ */
		vgid[3] = Vattach(HDFfid, -1, "w");
		Vsetname(vgid[3], "Swath Attributes");
		Vsetclass(vgid[3], "SWATH Vgroup");
		Vinsert(vgid[0], vgid[3]);



		/* Establish Swath in Structural MetaData Block */
		/* -------------------------------------------- */
		snprintf(utlbuf, sizeof(utlbuf), "%s%ld%s%s%s",
			"\tGROUP=SWATH_", (long)nSwath + 1,
			"\n\t\tSwathName=\"", swathname, "\"\n");

		strcat(utlbuf, "\t\tGROUP=Dimension\n");
		strcat(utlbuf, "\t\tEND_GROUP=Dimension\n");
		strcat(utlbuf, "\t\tGROUP=DimensionMap\n");
		strcat(utlbuf, "\t\tEND_GROUP=DimensionMap\n");
		strcat(utlbuf, "\t\tGROUP=IndexDimensionMap\n");
		strcat(utlbuf, "\t\tEND_GROUP=IndexDimensionMap\n");
		strcat(utlbuf, "\t\tGROUP=GeoField\n");
		strcat(utlbuf, "\t\tEND_GROUP=GeoField\n");
		strcat(utlbuf, "\t\tGROUP=DataField\n");
		strcat(utlbuf, "\t\tEND_GROUP=DataField\n");
		strcat(utlbuf, "\t\tGROUP=MergedFields\n");
		strcat(utlbuf, "\t\tEND_GROUP=MergedFields\n");
		CPLsnprintf(utlbuf2, sizeof(utlbuf2), "%s%ld%s",
			"\tEND_GROUP=SWATH_", (long)nSwath + 1, "\n");
		strcat(utlbuf, utlbuf2);


		status = EHinsertmeta(sdInterfaceID, "", "s", 1001L,
				      utlbuf, NULL);
	    }
	}
	else
	{
	    /* Too many files opened */
	    /* --------------------- */
	    status = -1;
	    strcpy(errbuf,
		   "No more than %d swaths may be open simultaneously");
	    strcat(errbuf, " (%s)");
	    HEpush(DFE_DENIED, "SWcreate", __FILE__, __LINE__);
	    HEreport(errbuf, NSWATH, swathname);
	}


	/* Assign swathID # & Load swath and SWXSwath table entries */
	/* -------------------------------------------------------- */
	if (status == 0)
	{

	    for (i = 0; i < NSWATH; i++)
	    {
		if (SWXSwath[i].active == 0)
		{
		    /*
		     * Set swathID, Set swath entry active, Store root Vgroup
		     * ID, Store sub Vgroup IDs, Store HDF-EOS file ID
		     */
		    swathID = i + idOffset;
		    SWXSwath[i].active = 1;
		    SWXSwath[i].IDTable = vgid[0];
		    SWXSwath[i].VIDTable[0] = vgid[1];
		    SWXSwath[i].VIDTable[1] = vgid[2];
		    SWXSwath[i].VIDTable[2] = vgid[3];
		    SWXSwath[i].fid = fid;
		    status = 0;
		    break;
		}
	    }

	}
    }
    return (swathID);
}


/*----------------------------------------------------------------------------|
|  BEGIN_PROLOG                                                               |
|                                                                             |
|  FUNCTION: SWattach                                                         |
|                                                                             |
|  DESCRIPTION:  Attaches to an existing swath within the file.               |
|                                                                             |
|                                                                             |
|  Return Value    Type     Units     Description                             |
|  ============   ======  =========   =====================================   |
|  swathID        int32               swath structure ID                      |
|                                                                             |
|  INPUTS:                                                                    |
|  fid            int32               HDF-EOS file ID                         |
|  swathname      char                swath structure name                    |
|                                                                             |
|  OUTPUTS:                                                                   |
|             None                                                            |
|                                                                             |
|  NOTES:                                                                     |
|                                                                             |
|                                                                             |
|   Date     Programmer   Description                                         |
|  ======   ============  =================================================   |
|  Jun 96   Joel Gales    Original Programmer                                 |
|  Apr 99   David Wynne   Modified test for memory allocation check when no   |
|                         SDSs are in the Swath, NCR22513                     |
|                                                                             |
|  END_PROLOG                                                                 |
-----------------------------------------------------------------------------*/
int32
SWattach(int32 fid, const char *swathname)

{
    intn            i;		/* Loop index */
    intn            j;		/* Loop index */
    intn            nswathopen = 0;	/* # of swath structures open */
    intn            status;	/* routine return status variable */

    uint8           acs;	/* Read/Write file access code */

    int32           HDFfid;	/* HDF file id */
    int32           vgRef;	/* Vgroup reference number */
    int32           vgid[4];	/* Vgroup ID array */
    int32           swathID = -1;	/* HDF-EOS swath ID */
    int32          *tags;	/* Pnt to Vgroup object tags array */
    int32          *refs;	/* Pnt to Vgroup object refs array */
    int32           dum;	/* dummy variable */
    int32           sdInterfaceID;	/* HDF SDS interface ID */
    int32           nObjects;	/* # of objects in Vgroup */
    int32           nSDS;	/* SDS counter */
    int32           l_index;	/* SDS l_index */
    int32           sdid;	/* SDS object ID */
    int32           idOffset = SWIDOFFSET;	/* Swath ID offset */

    char            name[80];	/* Vgroup name */
    char            class[80];	/* Vgroup class */
    char            errbuf[256];/* Buffer for error message */
    char            acsCode[1];	/* Read/Write access char: "r/w" */


    /* Check HDF-EOS file ID, get back HDF file ID and access code */
    /* ----------------------------------------------------------- */
    status = EHchkfid(fid, swathname, &HDFfid, &dum, &acs);


    if (status == 0)
    {
	/* Convert numeric access code to character */
	/* ---------------------------------------- */
	acsCode[0] = (acs == 1) ? 'w' : 'r';

	/* Determine number of swaths currently opened */
	/* ------------------------------------------- */
	for (i = 0; i < NSWATH; i++)
	{
	    nswathopen += SWXSwath[i].active;
	}

	/* If room for more ... */
	/* -------------------- */
	if (nswathopen < NSWATH)
	{

	    /* Search Vgroups for Swath */
	    /* ------------------------ */
	    vgRef = -1;

	    while (1)
	    {
		vgRef = Vgetid(HDFfid, vgRef);


		/* If no more Vgroups then exist while loop */
		/* ---------------------------------------- */
		if (vgRef == -1)
		{
		    break;
		}

		/* Get name and class of Vgroup */
		/* ---------------------------- */
		vgid[0] = Vattach(HDFfid, vgRef, "r");
		Vgetname(vgid[0], name);
		Vgetclass(vgid[0], class);


		/*
		 * If Vgroup with swathname and class SWATH found, load
		 * tables
		 */

		if (strcmp(name, swathname) == 0 &&
		    strcmp(class, "SWATH") == 0)
		{
		    /* Attach to "Fields" and "Swath Attributes" Vgroups */
		    /* ------------------------------------------------- */
		    tags = (int32 *) malloc(sizeof(int32) * 3);
		    if(tags == NULL)
		    { 
			HEpush(DFE_NOSPACE,"SWattach", __FILE__, __LINE__);
			return(-1);
		    }
		    refs = (int32 *) malloc(sizeof(int32) * 3);
		    if(refs == NULL)
		    { 
			HEpush(DFE_NOSPACE,"SWattach", __FILE__, __LINE__);
			free(tags);
			return(-1);
		    }
		    Vgettagrefs(vgid[0], tags, refs, 3);
		    vgid[1] = Vattach(HDFfid, refs[0], acsCode);
		    vgid[2] = Vattach(HDFfid, refs[1], acsCode);
		    vgid[3] = Vattach(HDFfid, refs[2], acsCode);
		    free(tags);
		    free(refs);

		    /* Setup External Arrays */
		    /* --------------------- */
		    for (i = 0; i < NSWATH; i++)
		    {
			/* Find empty entry in array */
			/* ------------------------- */
			if (SWXSwath[i].active == 0)
			{
			    /*
			     * Set swathID, Set swath entry active, Store
			     * root Vgroup ID, Store sub Vgroup IDs, Store
			     * HDF-EOS file ID
			     */
			    swathID = i + idOffset;
			    SWXSwath[i].active = 1;
			    SWXSwath[i].IDTable = vgid[0];
			    SWXSwath[i].VIDTable[0] = vgid[1];
			    SWXSwath[i].VIDTable[1] = vgid[2];
			    SWXSwath[i].VIDTable[2] = vgid[3];
			    SWXSwath[i].fid = fid;
			    break;
			}
		    }

		    /* Get SDS interface ID */
		    /* -------------------- */
		    status = SWchkswid(swathID, "SWattach", &dum,
				       &sdInterfaceID, &dum);


		    /* Access swath "Geolocation" SDS */
		    /* ------------------------------ */

		    /* Get # of entries within this Vgroup & search for SDS */
		    /* ---------------------------------------------------- */
		    nObjects = Vntagrefs(vgid[1]);

		    if (nObjects > 0)
		    {
			/* Get tag and ref # for Geolocation Vgroup objects */
			/* ------------------------------------------------ */
			tags = (int32 *) malloc(sizeof(int32) * nObjects);
			if(tags == NULL)
			{ 
			    HEpush(DFE_NOSPACE,"SWattach", __FILE__, __LINE__);
			    return(-1);
			}
			refs = (int32 *) malloc(sizeof(int32) * nObjects);
			if(refs == NULL)
			{ 
			    HEpush(DFE_NOSPACE,"SWattach", __FILE__, __LINE__);
			    free(tags);
			    return(-1);
			}
			Vgettagrefs(vgid[1], tags, refs, nObjects);

			/* Count number of SDS & allocate SDS ID array */
			/* ------------------------------------------- */
			nSDS = 0;
			for (j = 0; j < nObjects; j++)
			{
			    if (tags[j] == DFTAG_NDG)
			    {
				nSDS++;
			    }
			}
			SWXSwath[i].sdsID = (int32 *) calloc(nSDS, 4);
			if(SWXSwath[i].sdsID == NULL && nSDS != 0)
			{ 
			    HEpush(DFE_NOSPACE,"SWattach", __FILE__, __LINE__);
			    free(tags);
			    free(refs);
			    return(-1);
			}
			nSDS = 0;


			/* Fill SDS ID array */
			/* ----------------- */
			for (j = 0; j < nObjects; j++)
			{
			    /* If object is SDS then get id */
			    /* ---------------------------- */
			    if (tags[j] == DFTAG_NDG)
			    {
				l_index = SDreftoindex(sdInterfaceID, refs[j]);
				sdid = SDselect(sdInterfaceID, l_index);
				SWXSwath[i].sdsID[nSDS] = sdid;
				nSDS++;
				SWXSwath[i].nSDS++;
			    }
			}
			free(tags);
			free(refs);
		    }

		    /* Access swath "Data" SDS */
		    /* ----------------------- */

		    /* Get # of entries within this Vgroup & search for SDS */
		    /* ---------------------------------------------------- */
		    nObjects = Vntagrefs(vgid[2]);

		    if (nObjects > 0)
		    {
			/* Get tag and ref # for Data Vgroup objects */
			/* ----------------------------------------- */
			tags = (int32 *) malloc(sizeof(int32) * nObjects);
			if(tags == NULL)
			{ 
			    HEpush(DFE_NOSPACE,"SWattach", __FILE__, __LINE__);
			    return(-1);
			}
			refs = (int32 *) malloc(sizeof(int32) * nObjects);
			if(refs == NULL)
			{ 
			    HEpush(DFE_NOSPACE,"SWattach", __FILE__, __LINE__);
			    free(tags);
			    return(-1);
			}
			Vgettagrefs(vgid[2], tags, refs, nObjects);


			/* Count number of SDS & allocate SDS ID array */
			/* ------------------------------------------- */
			nSDS = 0;
			for (j = 0; j < nObjects; j++)
			{
			    if (tags[j] == DFTAG_NDG)
			    {
				nSDS++;
			    }
			}
			SWXSwath[i].sdsID = (int32 *)
			    realloc((void *) SWXSwath[i].sdsID,
				    (SWXSwath[i].nSDS + nSDS) * 4);
			if(SWXSwath[i].sdsID == NULL && nSDS != 0)
			{ 
			    HEpush(DFE_NOSPACE,"SWattach", __FILE__, __LINE__);
			    return(-1);
			}

			/* Fill SDS ID array */
			/* ----------------- */
			for (j = 0; j < nObjects; j++)
			{
			    /* If object is SDS then get id */
			    /* ---------------------------- */
			    if (tags[j] == DFTAG_NDG)
			    {
				l_index = SDreftoindex(sdInterfaceID, refs[j]);
				sdid = SDselect(sdInterfaceID, l_index);
				SWXSwath[i].sdsID[SWXSwath[i].nSDS] = sdid;
				SWXSwath[i].nSDS++;
			    }
			}
			free(tags);
			free(refs);
		    }
		    break;
		}

		/* Detach Vgroup if not desired Swath */
		/* ---------------------------------- */
		Vdetach(vgid[0]);
	    }

	    /* If Swath not found then set up error message */
	    /* -------------------------------------------- */
	    if (swathID == -1)
	    {
		HEpush(DFE_RANGE, "SWattach", __FILE__, __LINE__);
		HEreport("Swath: \"%s\" does not exist within HDF file.\n",
			 swathname);
	    }
	}
	else
	{
	    /* Too many files opened */
	    /* --------------------- */
	    swathID = -1;
	    strcpy(errbuf,
		   "No more than %d swaths may be open simultaneously");
	    strcat(errbuf, " (%s)");
	    HEpush(DFE_DENIED, "SWattach", __FILE__, __LINE__);
	    HEreport(errbuf, NSWATH, swathname);
	}

    }
    return (swathID);
}

/*----------------------------------------------------------------------------|
|  BEGIN_PROLOG                                                               |
|                                                                             |
|  FUNCTION: SWchkswid                                                        |
|                                                                             |
|  DESCRIPTION: Checks for valid swathID and returns file ID, SDS ID, and     |
|               swath Vgroup ID                                               |
|                                                                             |
|                                                                             |
|  Return Value    Type     Units     Description                             |
|  ============   ======  =========   =====================================   |
|  status         intn                return status (0) SUCCEED, (-1) FAIL    |
|                                                                             |
|  INPUTS:                                                                    |
|  swathID        int32               swath structure ID                      |
|  routname       char                Name of routine calling SWchkswid       |
|                                                                             |
|  OUTPUTS:                                                                   |
|  fid            int32               File ID                                 |
|  sdInterfaceID  int32               SDS interface ID                        |
|  swVgrpID       int32               swath Vgroup ID                         |
|                                                                             |
|  NOTES:                                                                     |
|                                                                             |
|                                                                             |
|   Date     Programmer   Description                                         |
|  ======   ============  =================================================   |
|  Jun 96   Joel Gales    Original Programmer                                 |
|                                                                             |
|  END_PROLOG                                                                 |
-----------------------------------------------------------------------------*/
static intn
SWchkswid(int32 swathID, const char *routname,
	  int32 * fid, int32 * sdInterfaceID, int32 * swVgrpID)

{
    intn            status = 0;	/* routine return status variable */
    uint8           l_access;	/* Read/Write access code */

    int32           idOffset = SWIDOFFSET;	/* Swath ID offset */

    char            message1[] =
    "Invalid swath id: %d in routine \"%s\".  ID must be >= %d and < %d.\n";
    char            message2[] =
    "Swath id %d in routine \"%s\" not active.\n";


    /* Check for valid swath id */
    /* ------------------------ */
    if (swathID < idOffset || swathID >= NSWATH + idOffset)
    {
	status = -1;
	HEpush(DFE_RANGE, "SWchkswid", __FILE__, __LINE__);
	HEreport(message1, swathID, routname, idOffset, NSWATH + idOffset);
    }
    else
    {
	/* Check for active swath ID */
	/* ------------------------- */
	if (SWXSwath[swathID % idOffset].active == 0)
	{
	    status = -1;
	    HEpush(DFE_GENAPP, "SWchkswid", __FILE__, __LINE__);
	    HEreport(message2, swathID, routname);
	}
	else
	{

	    /* Get file & SDS ids and Swath Vgroup */
	    /* ----------------------------------- */
	    status = EHchkfid(SWXSwath[swathID % idOffset].fid, " ", fid,
			      sdInterfaceID, &l_access);
	    *swVgrpID = SWXSwath[swathID % idOffset].IDTable;
	}
    }
    return (status);
}







/*----------------------------------------------------------------------------|
|  BEGIN_PROLOG                                                               |
|                                                                             |
|  FUNCTION: SWdefdim                                                         |
|                                                                             |
|  DESCRIPTION: Defines numerical value of dimension                          |
|                                                                             |
|                                                                             |
|  Return Value    Type     Units     Description                             |
|  ============   ======  =========   =====================================   |
|  status         intn                return status (0) SUCCEED, (-1) FAIL    |
|                                                                             |
|  INPUTS:                                                                    |
|  swathID        int32               swath structure ID                      |
|  dimname        char                Dimension name to define                |
|  dim            int32               Dimension value                         |
|                                                                             |
|  OUTPUTS:                                                                   |
|             None                                                            |
|                                                                             |
|  NOTES:                                                                     |
|                                                                             |
|                                                                             |
|   Date     Programmer   Description                                         |
|  ======   ============  =================================================   |
|  Jun 96   Joel Gales    Original Programmer                                 |
|  Dec 96   Joel Gales    Check that dim value >= 0                           |
|                                                                             |
|  END_PROLOG                                                                 |
-----------------------------------------------------------------------------*/
intn
SWdefdim(int32 swathID, char *dimname, int32 dim)

{
    intn            status;	/* routine return status variable */

    int32           fid;	/* HDF-EOS file id */
    int32           sdInterfaceID;	/* HDF SDS interface ID */
    int32           swVgrpID;	/* Swath root Vgroup ID */
    int32           idOffset = SWIDOFFSET;	/* Swath ID offset */

    char            swathname[80] /* Swath name */ ;


    /* Check for valid swath id */
    /* ------------------------ */
    status = SWchkswid(swathID, "SWdefdim", &fid, &sdInterfaceID, &swVgrpID);


    /* Make sure dimension >= 0 */
    /* ------------------------ */
    if (dim < 0)
    {
	status = -1;
	HEpush(DFE_GENAPP, "SWdefdim", __FILE__, __LINE__);
	HEreport("Dimension value for \"%s\" less than zero: %d.\n",
		 dimname, dim);
    }


    /* Write Dimension to Structural MetaData */
    /* -------------------------------------- */
    if (status == 0)
    {
	Vgetname(SWXSwath[swathID % idOffset].IDTable, swathname);
	status = EHinsertmeta(sdInterfaceID, swathname, "s", 0L,
			      dimname, &dim);
    }
    return (status);
}



/*----------------------------------------------------------------------------|
|  BEGIN_PROLOG                                                               |
|                                                                             |
|  FUNCTION: SWdiminfo                                                        |
|                                                                             |
|  DESCRIPTION: Returns size in bytes of named dimension                      |
|                                                                             |
|                                                                             |
|  Return Value    Type     Units     Description                             |
|  ============   ======  =========   =====================================   |
|  size           int32               Size of dimension                       |
|                                                                             |
|  INPUTS:                                                                    |
|  swathID        int32               swath structure id                      |
|  dimname        char                Dimension name                          |
|                                                                             |
|                                                                             |
|  OUTPUTS:                                                                   |
|             None                                                            |
|                                                                             |
|  NOTES:                                                                     |
|                                                                             |
|                                                                             |
|   Date     Programmer   Description                                         |
|  ======   ============  =================================================   |
|  Jun 96   Joel Gales    Original Programmer                                 |
|  Aug 96   Joel Gales    Make metadata ODL compliant                         |
|  Jan 97   Joel Gales    Check for metadata error status from EHgetmetavalue |
|                                                                             |
|  END_PROLOG                                                                 |
-----------------------------------------------------------------------------*/
int32
SWdiminfo(int32 swathID, const char *dimname)

{
    intn            status;	/* routine return status variable */

    int32           fid;	/* HDF-EOS file ID */
    int32           sdInterfaceID;	/* HDF SDS interface ID */
    int32           swVgrpID;	/* Swath root Vgroup ID */
    int32           size;	/* Dimension size */
    int32           idOffset = SWIDOFFSET;	/* Swath ID offset */


    char           *metabuf;	/* Pointer to structural metadata (SM) */
    char           *metaptrs[2];/* Pointers to begin and end of SM section */
    char            swathname[80];	/* Swath Name */
    char           *utlstr;	/* Utility string */


    /* Allocate space for utility string */
    /* --------------------------------- */
    utlstr = (char *) calloc(UTLSTR_MAX_SIZE, sizeof(char));
    if(utlstr == NULL)
    { 
	HEpush(DFE_NOSPACE,"SWdiminfo", __FILE__, __LINE__);
	return(-1);
    }
    /* Initialize return value */
    size = -1;

    /* Check Swath ID */
    status = SWchkswid(swathID, "SWdiminfo", &fid, &sdInterfaceID, &swVgrpID);

    if (status == 0)
    {
	/* Get swath name */
	Vgetname(SWXSwath[swathID % idOffset].IDTable, swathname);

	/* Get pointers to "Dimension" section within SM */
	metabuf = (char *) EHmetagroup(sdInterfaceID, swathname, "s",
				       "Dimension", metaptrs);

	if(metabuf == NULL)
	{
	    free(utlstr);
	    return(-1);
	}  

	/* Search for dimension name (surrounded by quotes) */
	snprintf(utlstr, UTLSTR_MAX_SIZE, "%s%s%s", "\"", dimname, "\"\n");
	metaptrs[0] = strstr(metaptrs[0], utlstr);

	/*
	 * If dimension found within swath structure then get dimension value
	 */
	if (metaptrs[0] < metaptrs[1] && metaptrs[0] != NULL)
	{
	    /* Set endptr at end of dimension definition entry */
	    metaptrs[1] = strstr(metaptrs[0], "\t\t\tEND_OBJECT");

	    status = EHgetmetavalue(metaptrs, "Size", utlstr);

	    if (status == 0)
	    {
		size = atoi(utlstr);
	    }
	    else
	    {
		HEpush(DFE_GENAPP, "SWdiminfo", __FILE__, __LINE__);
		HEreport("\"Size\" string not found in metadata.\n");
	    }
	}
	else
	{
	    HEpush(DFE_GENAPP, "SWdiminfo", __FILE__, __LINE__);
	    HEreport("Dimension \"%s\" not found.\n", dimname);
	}

	free(metabuf);
    }
    free(utlstr);

    return (size);
}




/*----------------------------------------------------------------------------|
|  BEGIN_PROLOG                                                               |
|                                                                             |
|  FUNCTION: SWmapinfo                                                        |
|                                                                             |
|  DESCRIPTION: Returns dimension mapping information                         |
|                                                                             |
|                                                                             |
|  Return Value    Type     Units     Description                             |
|  ============   ======  =========   =====================================   |
|  status         intn                return status (0) SUCCEED, (-1) FAIL    |
|                                                                             |
|  INPUTS:                                                                    |
|  swathID        int32               swath structure id                      |
|  geodim         char                geolocation dimension name              |
|  datadim        char                data dimension name                     |
|                                                                             |
|  OUTPUTS:                                                                   |
|  offset         int32               mapping offset                          |
|  increment      int32               mapping increment                       |
|                                                                             |
|  NOTES:                                                                     |
|                                                                             |
|                                                                             |
|   Date     Programmer   Description                                         |
|  ======   ============  =================================================   |
|  Jun 96   Joel Gales    Original Programmer                                 |
|  Aug 96   Joel Gales    Make metadata ODL compliant                         |
|  Jan 97   Joel Gales    Check for metadata error status from EHgetmetavalue |
|                                                                             |
|  END_PROLOG                                                                 |
-----------------------------------------------------------------------------*/
intn
SWmapinfo(int32 swathID, const char *geodim, const char *datadim, int32 * offset,
	  int32 * increment)

{
    intn            status;	/* routine return status variable */
    intn            statmeta = 0;	/* EHgetmetavalue return status */

    int32           fid;	/* HDF-EOS file ID */
    int32           sdInterfaceID;	/* HDF SDS interface ID */
    int32           swVgrpID;	/* Swath root Vgroup ID */
    int32           idOffset = SWIDOFFSET;	/* Swath ID offset */

    char           *metabuf;	/* Pointer to structural metadata (SM) */
    char           *metaptrs[2];/* Pointers to begin and end of SM section */
    char            swathname[80];	/* Swath Name */
    char           *utlstr;	/* Utility string */


    /* Allocate space for utility string */
    /* --------------------------------- */
    utlstr = (char *) calloc(UTLSTR_MAX_SIZE, sizeof(char));
    if(utlstr == NULL)
    { 
	HEpush(DFE_NOSPACE,"SWmapinfo", __FILE__, __LINE__);
	return(-1);
    }
    /* Initialize return values */
    *offset = -1;
    *increment = -1;

    /* Check Swath ID */
    status = SWchkswid(swathID, "SWmapinfo", &fid, &sdInterfaceID, &swVgrpID);

    if (status == 0)
    {
	/* Get swath name */
	Vgetname(SWXSwath[swathID % idOffset].IDTable, swathname);

	/* Get pointers to "DimensionMap" section within SM */
	metabuf = (char *) EHmetagroup(sdInterfaceID, swathname, "s",
				       "DimensionMap", metaptrs);
	if(metabuf == NULL)
	{
	    free(utlstr);
	    return(-1);
	}

	/* Search for mapping - GeoDim/DataDim (surrounded by quotes) */
	snprintf(utlstr, UTLSTR_MAX_SIZE, "%s%s%s%s%s", "\t\t\t\tGeoDimension=\"", geodim,
		"\"\n\t\t\t\tDataDimension=\"", datadim, "\"\n");
	metaptrs[0] = strstr(metaptrs[0], utlstr);

	/*
	 * If mapping found within swath structure then get offset and
	 * increment value
	 */
	if (metaptrs[0] < metaptrs[1] && metaptrs[0] != NULL)
	{
	    /* Get Offset */
	    statmeta = EHgetmetavalue(metaptrs, "Offset", utlstr);
	    if (statmeta == 0)
	    {
		*offset = atoi(utlstr);
	    }
	    else
	    {
		status = -1;
		HEpush(DFE_GENAPP, "SWmapinfo", __FILE__, __LINE__);
		HEreport("\"Offset\" string not found in metadata.\n");
	    }


	    /* Get Increment */
	    statmeta = EHgetmetavalue(metaptrs, "Increment", utlstr);
	    if (statmeta == 0)
	    {
		*increment = atoi(utlstr);
	    }
	    else
	    {
		status = -1;
		HEpush(DFE_GENAPP, "SWmapinfo", __FILE__, __LINE__);
		HEreport("\"Increment\" string not found in metadata.\n");
	    }
	}
	else
	{
	    status = -1;
	    HEpush(DFE_GENAPP, "SWmapinfo", __FILE__, __LINE__);
	    HEreport("Mapping \"%s/%s\" not found.\n", geodim, datadim);
	}

	free(metabuf);
    }
    free(utlstr);
    return (status);
}




/*----------------------------------------------------------------------------|
|  BEGIN_PROLOG                                                               |
|                                                                             |
|  FUNCTION: SWidxmapinfo                                                     |
|                                                                             |
|  DESCRIPTION: Returns l_indexed mapping information                           |
|                                                                             |
|                                                                             |
|  Return Value    Type     Units     Description                             |
|  ============   ======  =========   =====================================   |
|  gsize          int32               Number of l_index values (sz of geo dim)  |
|                                                                             |
|  INPUTS:                                                                    |
|  swathID        int32               swath structure id                      |
|  geodim         char                geolocation dimension name              |
|  datadim        char                data dimension name                     |
|                                                                             |
|                                                                             |
|  OUTPUTS:                                                                   |
|  l_index          int32               array of l_index values                   |
|                                                                             |
|  NOTES:                                                                     |
|                                                                             |
|                                                                             |
|   Date     Programmer   Description                                         |
|  ======   ============  =================================================   |
|  Jun 96   Joel Gales    Original Programmer                                 |
|                                                                             |
|  END_PROLOG                                                                 |
-----------------------------------------------------------------------------*/
int32
SWidxmapinfo(int32 swathID, const char *geodim, const char *datadim, int32 l_index[])
{
    intn            status;	/* routine return status variable */

    int32           fid;	/* HDF-EOS file ID */
    int32           sdInterfaceID;	/* HDF SDS interface ID */
    int32           swVgrpID;	/* Swath root Vgroup ID */
    int32           idOffset = SWIDOFFSET;	/* Swath ID offset */
    int32           vgid;	/* Swath Attributes Vgroup ID */
    int32           vdataID;	/* Index Mapping Vdata ID */
    int32           gsize = -1;	/* Size of geo dim */

    char            utlbuf[256];/* Utility buffer */


    /* Check Swath ID */
    status = SWchkswid(swathID, "SWidxmapinfo",
		       &fid, &sdInterfaceID, &swVgrpID);

    if (status == 0)
    {
	/* Find Index Mapping Vdata with Swath Attributes Vgroup */
	snprintf(utlbuf, sizeof(utlbuf), "%s%s%s%s", "INDXMAP:", geodim, "/", datadim);
	vgid = SWXSwath[swathID % idOffset].VIDTable[2];
	vdataID = EHgetid(fid, vgid, utlbuf, 1, "r");

	/* If found then get geodim size & read l_index mapping values */
	if (vdataID != -1)
	{
	    gsize = SWdiminfo(swathID, geodim);

	    VSsetfields(vdataID, "Index");
	    VSread(vdataID, (uint8 *) l_index, 1, FULL_INTERLACE);
	    VSdetach(vdataID);
	}
	else
	{
	    /*status = -1;*/
	    HEpush(DFE_GENAPP, "SWidxmapinfo", __FILE__, __LINE__);
	    HEreport("Index Mapping \"%s\" not found.\n", utlbuf);
	}
    }
    return (gsize);
}




/*----------------------------------------------------------------------------|
|  BEGIN_PROLOG                                                               |
|                                                                             |
|  FUNCTION: SWcompinfo                                                       |
|                                                                             |
|  DESCRIPTION:                                                               |
|                                                                             |
|                                                                             |
|  Return Value    Type     Units     Description                             |
|  ============   ======  =========   =====================================   |
|  status         intn                                                        |
|                                                                             |
|  INPUTS:                                                                    |
|  swathID        int32                                                       |
|  compcode       int32                                                       |
|  compparm       intn                                                        |
|                                                                             |
|                                                                             |
|  OUTPUTS:                                                                   |
|             None                                                            |
|                                                                             |
|  NOTES:                                                                     |
|                                                                             |
|                                                                             |
|   Date     Programmer   Description                                         |
|  ======   ============  =================================================   |
|  Oct 96   Joel Gales    Original Programmer                                 |
|  Jan 97   Joel Gales    Check for metadata error status from EHgetmetavalue |
|                                                                             |
|  END_PROLOG                                                                 |
-----------------------------------------------------------------------------*/
intn
SWcompinfo(int32 swathID, const char *fieldname, int32 * compcode, intn compparm[])
{
    intn            i;		/* Loop Index */
    intn            status;	/* routine return status variable */
    intn            statmeta = 0;	/* EHgetmetavalue return status */

    int32           fid;	/* HDF-EOS file ID */
    int32           sdInterfaceID;	/* HDF SDS interface ID */
    int32           swVgrpID;	/* Swath root Vgroup ID */
    int32           idOffset = SWIDOFFSET;	/* Swath ID offset */

    char           *metabuf;	/* Pointer to structural metadata (SM) */
    char           *metaptrs[2];/* Pointers to begin and end of SM section */
    char            swathname[80];	/* Swath Name */
    char           *utlstr;     /* Utility string */

    const char           *HDFcomp[5] = {"HDFE_COMP_NONE", "HDFE_COMP_RLE",
	"HDFE_COMP_NBIT", "HDFE_COMP_SKPHUFF",
    "HDFE_COMP_DEFLATE"};	/* Compression Codes */

    /* Allocate space for utility string */
    /* --------------------------------- */
    utlstr = (char *) calloc(UTLSTR_MAX_SIZE, sizeof(char));
    if(utlstr == NULL)
    { 
	HEpush(DFE_NOSPACE,"SWcompinfo", __FILE__, __LINE__);
	return(-1);
    }

    /* Check Swath ID */
    status = SWchkswid(swathID, "SWcompinfo",
		       &fid, &sdInterfaceID, &swVgrpID);

    if (status == 0)
    {
	/* Get swath name */
	Vgetname(SWXSwath[swathID % idOffset].IDTable, swathname);

	/* Get pointers to "DataField" section within SM */
	metabuf = (char *) EHmetagroup(sdInterfaceID, swathname, "s",
				       "DataField", metaptrs);
	if(metabuf == NULL)
	{
	    free(utlstr);
	    return(-1);
	}
	/* Search for field */
	snprintf(utlstr, UTLSTR_MAX_SIZE, "%s%s%s", "\"", fieldname, "\"\n");
	metaptrs[0] = strstr(metaptrs[0], utlstr);

	/* If not found then search in "GeoField" section */
	if (metaptrs[0] > metaptrs[1] || metaptrs[0] == NULL)
	{
	    free(metabuf);

	    /* Get pointers to "GeoField" section within SM */
	    metabuf = (char *) EHmetagroup(sdInterfaceID, swathname, "s",
					   "GeoField", metaptrs);
	    if(metabuf == NULL)
	    {
		free(utlstr);
		return(-1);
	    }
	    /* Search for field */
	    snprintf(utlstr, UTLSTR_MAX_SIZE, "%s%s%s", "\"", fieldname, "\"\n");
	    metaptrs[0] = strstr(metaptrs[0], utlstr);
	}


	/* If field found and user wants compression code ... */
	if (metaptrs[0] < metaptrs[1] && metaptrs[0] != NULL)
	{
	    if (compcode != NULL)
	    {
		/* Set endptr at end of field's definition entry */
		metaptrs[1] = strstr(metaptrs[0], "\t\t\tEND_OBJECT");

		/* Get compression type */
		statmeta = EHgetmetavalue(metaptrs, "CompressionType", utlstr);

		/*
		 * Default is no compression if "CompressionType" string not
		 * in metadata
		 */
		*compcode = HDFE_COMP_NONE;

		/* If compression code is found ... */
		if (statmeta == 0)
		{
		    /* Loop through compression types until match */
		    for (i = 0; i < 5; i++)
		    {
			if (strcmp(utlstr, HDFcomp[i]) == 0)
			{
			    *compcode = i;
			    break;
			}
		    }
		}
	    }

	    /* If user wants compression parameters ... */
	    if (compparm != NULL && compcode != NULL)
	    {
		/* Initialize to zero */
		for (i = 0; i < 4; i++)
		{
		    compparm[i] = 0;
		}

		/*
		 * Get compression parameters if NBIT or DEFLATE compression
		 */
		if (*compcode == HDFE_COMP_NBIT)
		{
		    statmeta =
			EHgetmetavalue(metaptrs, "CompressionParams", utlstr);
		    if (statmeta == 0)
		    {
			sscanf(utlstr, "(%d,%d,%d,%d)",
			       &compparm[0], &compparm[1],
			       &compparm[2], &compparm[3]);
		    }
		    else
		    {
			status = -1;
			HEpush(DFE_GENAPP, "SWcompinfo", __FILE__, __LINE__);
			HEreport(
				 "\"CompressionParams\" string not found in metadata.\n");
		    }
		}
		else if (*compcode == HDFE_COMP_DEFLATE)
		{
		    statmeta =
			EHgetmetavalue(metaptrs, "DeflateLevel", utlstr);
		    if (statmeta == 0)
		    {
			sscanf(utlstr, "%d", &compparm[0]);
		    }
		    else
		    {
			status = -1;
			HEpush(DFE_GENAPP, "SWcompinfo", __FILE__, __LINE__);
			HEreport(
			"\"DeflateLevel\" string not found in metadata.\n");
		    }
		}
	    }
	}
	else
	{
	    HEpush(DFE_GENAPP, "SWcompinfo", __FILE__, __LINE__);
	    HEreport("Fieldname \"%s\" not found.\n", fieldname);
	}

	free(metabuf);
    }
    free(utlstr);
    
    return (status);
}



/*----------------------------------------------------------------------------|
|  BEGIN_PROLOG                                                               |
|                                                                             |
|  FUNCTION: SWfinfo                                                          |
|                                                                             |
|  DESCRIPTION: Returns field info                                            |
|                                                                             |
|                                                                             |
|  Return Value    Type     Units     Description                             |
|  ============   ======  =========   =====================================   |
|  status         intn                return status (0) SUCCEED, (-1) FAIL    |
|                                                                             |
|  INPUTS:                                                                    |
|  swathID        int32               swath structure id                      |
|  fieldtype      const char          fieldtype (geo or data)                 |
|  fieldname      const char          name of field                           |
|                                                                             |
|                                                                             |
|  OUTPUTS:                                                                   |
|  rank           int32               rank of field (# of dims)               |
|  dims           int32               field dimensions                        |
|  numbertype     int32               field number type                       |
|  dimlist        char                field dimension list                    |
|                                                                             |
|  NOTES:                                                                     |
|                                                                             |
|                                                                             |
|   Date     Programmer   Description                                         |
|  ======   ============  =================================================   |
|  Jun 96   Joel Gales    Original Programmer                                 |
|  Aug 96   Joel Gales    Make metadata ODL compliant                         |
|  Jan 97   Joel Gales    Check for metadata error status from EHgetmetavalue |
|                                                                             |
|  END_PROLOG                                                                 |
-----------------------------------------------------------------------------*/
static int32
SWfinfo(int32 swathID, const char *fieldtype, const char *fieldname,
        int32 *rank, int32 dims[], int32 *numbertype, char *dimlist)

{
    intn            i;		/* Loop index */
    intn            j;		/* Loop index */
    intn            status;	/* routine return status variable */
    intn            statmeta = 0;	/* EHgetmetavalue return status */

    int32           fid;	/* HDF-EOS file ID */
    int32           sdInterfaceID;	/* HDF SDS interface ID */
    int32           idOffset = SWIDOFFSET;	/* Swath ID offset */
    int32           fsize;	/* field size in bytes */
    int32           ndims = 0;	/* Number of dimensions */
    int32           slen[8];	/* Length of each entry in parsed string */
    int32           dum;	/* Dummy variable */
    int32           vdataID;	/* 1d field vdata ID */

    uint8          *buf;	/* One-Dim field buffer */

    char           *metabuf;	/* Pointer to structural metadata (SM) */
    char           *metaptrs[2];/* Pointers to begin and end of SM section */
    char            swathname[80];	/* Swath Name */
    char           *utlstr;	/* Utility string */
    char           *ptr[8];	/* String pointers for parsed string */
    char            dimstr[64];	/* Individual dimension entry string */


    /* Allocate space for utility string */
    /* --------------------------------- */
    utlstr = (char *) calloc(UTLSTR_MAX_SIZE, sizeof(char));
    if(utlstr == NULL)
    { 
	HEpush(DFE_NOSPACE,"SWfinfo", __FILE__, __LINE__);
	return(-1);
    }

    /* Initialize rank and numbertype to -1 (error) */
    /* -------------------------------------------- */
    *rank = -1;
    *numbertype = -1;

    /* Get HDF-EOS file ID and SDS interface ID */
    status = SWchkswid(swathID, "SWfinfo", &fid, &sdInterfaceID, &dum);

    /* Get swath name */
    Vgetname(SWXSwath[swathID % idOffset].IDTable, swathname);

    /* Get pointers to appropriate "Field" section within SM */
    if (strcmp(fieldtype, "Geolocation Fields") == 0)
    {
	metabuf = EHmetagroup(sdInterfaceID, swathname, "s",
				       "GeoField", metaptrs);
	
	if(metabuf == NULL)
	{
	    free(utlstr);
	    return(-1);
	}
    }
    else
    {
	metabuf = EHmetagroup(sdInterfaceID, swathname, "s",
				       "DataField", metaptrs);
	if(metabuf == NULL)
	{
	    free(utlstr);
	    return(-1);
	}
    }


    /* Search for field */
    snprintf(utlstr, UTLSTR_MAX_SIZE, "%s%s%s", "\"", fieldname, "\"\n");
    metaptrs[0] = strstr(metaptrs[0], utlstr);

    /* If field found ... */
    if (metaptrs[0] < metaptrs[1] && metaptrs[0] != NULL)
    {
	/* Get DataType string */
	statmeta = EHgetmetavalue(metaptrs, "DataType", utlstr);

	/* Convert to numbertype code */
	if (statmeta == 0)
	    *numbertype = EHnumstr(utlstr);
	else
	{
	    status = -1;
	    HEpush(DFE_GENAPP, "SWfinfo", __FILE__, __LINE__);
	    HEreport("\"DataType\" string not found in metadata.\n");
	}


	/*
	 * Get DimList string and trim off leading and trailing parens "()"
	 */
	statmeta = EHgetmetavalue(metaptrs, "DimList", utlstr);

	if (statmeta == 0)
	{
	    memmove(utlstr, utlstr + 1, strlen(utlstr) - 2);
	    utlstr[strlen(utlstr) - 2] = 0;

	    /* Parse trimmed DimList string and get rank */
	    ndims = EHparsestr(utlstr, ',', ptr, slen);
	    *rank = ndims;
	}
	else
	{
	    status = -1;
	    HEpush(DFE_GENAPP, "SWfinfo", __FILE__, __LINE__);
	    HEreport("\"DimList\" string not found in metadata.\n");
	}

	/* If dimension list is desired by user then initialize length to 0 */
	if (dimlist != NULL)
	{
	    dimlist[0] = 0;
	}

	/*
	 * Copy each entry in DimList and remove leading and trailing quotes,
	 * Get dimension sizes and concatenate dimension names to dimension
	 * list
	 */
	for (i = 0; i < ndims; i++)
	{
	    memcpy(dimstr, ptr[i] + 1, slen[i] - 2);
	    dimstr[slen[i] - 2] = 0;
	    dims[i] = SWdiminfo(swathID, dimstr);
	    if (dimlist != NULL)
	    {
		if (i > 0)
		{
		    strcat(dimlist, ",");
		}
		strcat(dimlist, dimstr);
	    }

	}


	/* Appendable Field Section */
	/* ------------------------ */
	if (dims[0] == 0)
	{
	    /* One-Dimensional Field */
	    if (*rank == 1)
	    {
		/* Get vdata ID */
		status = SW1dfldsrch(fid, swathID, fieldname, "r",
				     &dum, &vdataID, &dum);

		/* Get actual size of field */
		dims[0] = VSelts(vdataID);

		/*
		 * If size=1 then check where actual record of
		 * "initialization" record
		 */
		if (dims[0] == 1)
		{
		    /* Get record size and read 1st record */
		    fsize = VSsizeof(vdataID, (char *)fieldname);
		    buf = (uint8 *) calloc(fsize, 1);
		    if(buf == NULL)
		    { 
			HEpush(DFE_NOSPACE,"SWfinfo", __FILE__, __LINE__);
			free(utlstr);
			return(-1);
		    }
		    VSsetfields(vdataID, fieldname);
		    VSseek(vdataID, 0);
		    VSread(vdataID, (uint8 *) buf, 1, FULL_INTERLACE);

		    /* Sum up "bytes" in record */
		    for (i = 0, j = 0; i < fsize; i++)
		    {
			j += buf[i];
		    }

		    /*
		     * If filled with 255 then "initialization" record,
		     * actual number of records = 0
		     */
		    if (j == 255 * fsize)
		    {
			dims[0] = 0;
		    }

		    free(buf);
		}
		/* Detach from 1d field */
		VSdetach(vdataID);
	    }
	    else
	    {
		/* Get actual size of Multi-Dimensional Field */
		status = SWSDfldsrch(swathID, sdInterfaceID, fieldname,
				     &dum, &dum, &dum, &dum, dims,
				     &dum);
	    }
	}
    }
    free(metabuf);

    if (*rank == -1)
    {
	status = -1;
    }
    free(utlstr);
     
    return (status);
}





/*----------------------------------------------------------------------------|
|  BEGIN_PROLOG                                                               |
|                                                                             |
|  FUNCTION: SWfieldinfo                                                      |
|                                                                             |
|  DESCRIPTION: Wrapper around SWfinfo                                        |
|                                                                             |
|                                                                             |
|  Return Value    Type     Units     Description                             |
|  ============   ======  =========   =====================================   |
|  status         intn                return status (0) SUCCEED, (-1) FAIL    |
|                                                                             |
|  INPUTS:                                                                    |
|  swathID        int32               swath structure id                      |
|  fieldname      const char          name of field                           |
|                                                                             |
|                                                                             |
|  OUTPUTS:                                                                   |
|  rank           int32               rank of field (# of dims)               |
|  dims           int32               field dimensions                        |
|  numbertype     int32               field number type                       |
|  dimlist        char                field dimension list                    |
|                                                                             |
|  NOTES:                                                                     |
|                                                                             |
|                                                                             |
|   Date     Programmer   Description                                         |
|  ======   ============  =================================================   |
|  Jun 96   Joel Gales    Original Programmer                                 |
|                                                                             |
|  END_PROLOG                                                                 |
-----------------------------------------------------------------------------*/
intn
SWfieldinfo(int32 swathID, const char *fieldname, int32 * rank, int32 dims[],
	    int32 * numbertype, char *dimlist)

{
    intn            status;	/* routine return status variable */

    int32           fid;	/* HDF-EOS file ID */
    int32           sdInterfaceID;	/* HDF SDS interface ID */
    int32           swVgrpID;	/* Swath root Vgroup ID */


    /* Check for valid swath id */
    status = SWchkswid(swathID, "SWfieldinfo", &fid,
		       &sdInterfaceID, &swVgrpID);
    if (status == 0)
    {
	/* Check for field within Geolocatation Fields */
	status = SWfinfo(swathID, "Geolocation Fields", fieldname,
			 rank, dims, numbertype, dimlist);

	/* If not there then check within Data Fields */
	if (status == -1)
	{
	    status = SWfinfo(swathID, "Data Fields", fieldname,
			     rank, dims, numbertype, dimlist);
	}

	/* If not there either then can't be found */
	if (status == -1)
	{
	    HEpush(DFE_GENAPP, "SWfieldinfo", __FILE__, __LINE__);
	    HEreport("Fieldname \"%s\" not found.\n", fieldname);
	}
    }
    return (status);
}






/*----------------------------------------------------------------------------|
|  BEGIN_PROLOG                                                               |
|                                                                             |
|  FUNCTION: SWdefdimmap                                                      |
|                                                                             |
|  DESCRIPTION: Defines mapping between geolocation and data dimensions       |
|                                                                             |
|                                                                             |
|  Return Value    Type     Units     Description                             |
|  ============   ======  =========   =====================================   |
|  status         intn                return status (0) SUCCEED, (-1) FAIL    |
|                                                                             |
|  INPUTS:                                                                    |
|  swathID        int32               swath structure ID                      |
|  geodim         char                Geolocation dimension                   |
|  datadim        char                Data dimension                          |
|  offset         int32               Mapping offset                          |
|  increment      int32               Mapping increment                       |
|                                                                             |
|  OUTPUTS:                                                                   |
|             None                                                            |
|                                                                             |
|  NOTES:                                                                     |
|                                                                             |
|                                                                             |
|   Date     Programmer   Description                                         |
|  ======   ============  =================================================   |
|  Jun 96   Joel Gales    Original Programmer                                 |
|                                                                             |
|  END_PROLOG                                                                 |
-----------------------------------------------------------------------------*/
intn
SWdefdimmap(int32 swathID, const char *geodim, const char *datadim, int32 offset,
	    int32 increment)

{
    intn            status;	/* routine return status variable */

    int32           fid;	/* HDF-EOS file ID */
    int32           sdInterfaceID;	/* HDF SDS interface ID */
    int32           size;	/* Size of geo dim */
    int32           idOffset = SWIDOFFSET;	/* Swath ID offset */
    int32           dum;	/* Dummy variable */
    int32           metadata[2];/* Offset & Increment (passed to metadata) */

    char            mapname[80];/* Mapping name (geodim/datadim) */
    char            swathname[80];	/* Swath name */

    /* Check Swath ID */
    status = SWchkswid(swathID, "SWdefdimmap", &fid, &sdInterfaceID, &dum);

    if (status == 0)
    {

	/* Search Dimension Vdata for dimension entries */
	/* -------------------------------------------- */
	size = SWdiminfo(swathID, geodim);
	if (size == -1)
	{
	    status = -1;
	    HEpush(DFE_GENAPP, "SWdefdimmap", __FILE__, __LINE__);
	    HEreport("Geolocation dimension name: \"%s\" not found.\n",
		     geodim);
	}
	/* Data Dimension Search */
	/* --------------------- */
	if (status == 0)
	{
	    size = SWdiminfo(swathID, datadim);
	    if (size == -1)
	    {
		status = -1;
		HEpush(DFE_GENAPP, "SWdefdimmap", __FILE__, __LINE__);
		HEreport("Data dimension name: \"%s\" not found.\n",
			 datadim);
	    }
	}

	/* Write Dimension Map to Structural MetaData */
	/* ------------------------------------------ */
	if (status == 0)
	{
	    snprintf(mapname, sizeof(mapname), "%s%s%s", geodim, "/", datadim);
	    metadata[0] = offset;
	    metadata[1] = increment;

	    Vgetname(SWXSwath[swathID % idOffset].IDTable, swathname);
	    status = EHinsertmeta(sdInterfaceID, swathname, "s", 1L,
				  mapname, metadata);

	}
    }
    return (status);
}



/*----------------------------------------------------------------------------|
|  BEGIN_PROLOG                                                               |
|                                                                             |
|  FUNCTION: SWdefidxmap                                                      |
|                                                                             |
|  DESCRIPTION: Defines l_indexed (non-linear) mapping between geolocation      |
|               and data dimensions                                           |
|                                                                             |
|                                                                             |
|  Return Value    Type     Units     Description                             |
|  ============   ======  =========   =====================================   |
|  status         intn                return status (0) SUCCEED, (-1) FAIL    |
|                                                                             |
|  INPUTS:                                                                    |
|  swathID        int32               swath structure ID                      |
|  geodim         char                Geolocation dimension                   |
|  datadim        char                Data dimension                          |
|  l_index          int32               Index mapping array                     |
|                                                                             |
|  OUTPUTS:                                                                   |
|             None                                                            |
|                                                                             |
|  NOTES:                                                                     |
|                                                                             |
|                                                                             |
|   Date     Programmer   Description                                         |
|  ======   ============  =================================================   |
|  Jun 96   Joel Gales    Original Programmer                                 |
|                                                                             |
|  END_PROLOG                                                                 |
-----------------------------------------------------------------------------*/
intn
SWdefidxmap(int32 swathID, const char *geodim, const char *datadim, int32 l_index[])

{
    intn            status;	/* routine return status variable */

    int32           fid;	/* HDF-EOS file ID */
    int32           sdInterfaceID;	/* HDF SDS interface ID */
    int32           attrVgrpID;	/* Swath attribute ID */
    int32           vdataID;	/* Mapping Index Vdata ID */
    int32           gsize;	/* Size of geo dim */
    int32           dsize;	/* Size of data dim */
    int32           idOffset = SWIDOFFSET;	/* Swath ID offset */
    int32           dum;	/* Dummy variable */

    uint8          *buf;	/* Vdata field buffer */

    char            mapname[80];/* Mapping name (geodim/datadim) */
    char            swathname[80];	/* Swath name */
    char            utlbuf[256];/* Utility buffer */


    /* Check Swath ID */
    status = SWchkswid(swathID, "SWdefidxmap", &fid, &sdInterfaceID, &dum);
    if (status == 0)
    {
	/* Search Dimension Vdata for dimension entries */
	/* -------------------------------------------- */

	/* Geo Dimension Search */
	/* -------------------- */
       
	gsize = SWdiminfo(swathID, geodim);

	if (gsize == -1)
	{
	    status = -1;
	    HEpush(DFE_GENAPP, "SWdefidxmap", __FILE__, __LINE__);
	    HEreport("Geolocation dimension name: \"%s\" not found.\n",
		     geodim);
	}
	/* Data Dimension Search */
	/* --------------------- */
	if (status == 0)
	{
	    dsize = SWdiminfo(swathID, datadim);
	    if (dsize == -1)
	    {
		status = -1;
		HEpush(DFE_GENAPP, "SWdefidxmap", __FILE__, __LINE__);
		HEreport("Data dimension name: \"%s\" not found.\n",
			 datadim);
	    }
	}
	/* Define Index Vdata and Store Index Array */
	/* ---------------------------------------- */
	if (status == 0)
	{
	    /* Get attribute Vgroup ID and allocate data buffer */
	    /* ------------------------------------------------ */
	    attrVgrpID = SWXSwath[swathID % idOffset].VIDTable[2];
	    buf = (uint8 *) calloc(4 * gsize, 1);
	    if(buf == NULL)
	    { 
		HEpush(DFE_NOSPACE,"SWdefidxmap", __FILE__, __LINE__);
		return(-1);
	    }

	    /* Name: "INDXMAP:" + geodim + "/" + datadim */
	    snprintf(utlbuf, sizeof(utlbuf), "%s%s%s%s", "INDXMAP:", geodim, "/", datadim);

	    vdataID = VSattach(fid, -1, "w");
	    VSsetname(vdataID, utlbuf);

	    /* Attribute Class */
	    VSsetclass(vdataID, "Attr0.0");

	    /* Fieldname is "Index" */
	    VSfdefine(vdataID, "Index", DFNT_INT32, gsize);
	    VSsetfields(vdataID, "Index");
	    memcpy(buf, l_index, 4 * gsize);

	    /* Write to vdata and free data buffer */
	    VSwrite(vdataID, buf, 1, FULL_INTERLACE);
	    free(buf);

	    /* Insert in Attribute Vgroup and detach Vdata */
	    Vinsert(attrVgrpID, vdataID);
	    VSdetach(vdataID);


	    /* Write to Structural Metadata */
	    snprintf(mapname, sizeof(mapname), "%s%s%s", geodim, "/", datadim);
	    Vgetname(SWXSwath[swathID % idOffset].IDTable, swathname);
	    status = EHinsertmeta(sdInterfaceID, swathname, "s", 2L,
				  mapname, &dum);

	}
    }
    return (status);

}


/*----------------------------------------------------------------------------|
|  BEGIN_PROLOG                                                               |
|                                                                             |
|  FUNCTION: SWdefcomp                                                        |
|                                                                             |
|  DESCRIPTION: Defines compression type and parameters                       |
|                                                                             |
|                                                                             |
|  Return Value    Type     Units     Description                             |
|  ============   ======  =========   =====================================   |
|  status         intn                return status (0) SUCCEED, (-1) FAIL    |
|                                                                             |
|  INPUTS:                                                                    |
|  swathID        int32               swath structure ID                      |
|  compcode       int32               compression code                        |
|  compparm       intn                compression parameters                  |
|                                                                             |
|  OUTPUTS:                                                                   |
|             None                                                            |
|                                                                             |
|  NOTES:                                                                     |
|                                                                             |
|                                                                             |
|   Date     Programmer   Description                                         |
|  ======   ============  =================================================   |
|  Sep 96   Joel Gales    Original Programmer                                 |
|                                                                             |
|  END_PROLOG                                                                 |
-----------------------------------------------------------------------------*/
intn
SWdefcomp(int32 swathID, int32 compcode, intn compparm[])
{
    intn            status = 0;	/* routine return status variable */

    int32           fid;	/* HDF-EOS file id */
    int32           sdInterfaceID;	/* HDF SDS interface ID */
    int32           swVgrpID;	/* Swath root Vgroup ID */
    int32           idOffset = SWIDOFFSET;	/* Swath ID offset */
    int32           sID;	/* swathID - offset */


    /* Check for valid swath id */
    status = SWchkswid(swathID, "SWdefcomp", &fid, &sdInterfaceID, &swVgrpID);

    if (status == 0)
    {
	sID = swathID % idOffset;

	/* Set compression code in compression external array */
	SWXSwath[sID].compcode = compcode;

	switch (compcode)
	{
	    /* Set NBIT compression parameters in compression external array */
	case HDFE_COMP_NBIT:

	    SWXSwath[sID].compparm[0] = compparm[0];
	    SWXSwath[sID].compparm[1] = compparm[1];
	    SWXSwath[sID].compparm[2] = compparm[2];
	    SWXSwath[sID].compparm[3] = compparm[3];

	    break;

	    /* Set GZIP compression parameter in compression external array */
	case HDFE_COMP_DEFLATE:

	    SWXSwath[sID].compparm[0] = compparm[0];

	    break;

	}
    }

    return (status);
}

/*----------------------------------------------------------------------------|
|  BEGIN_PROLOG                                                               |
|                                                                             |
|  FUNCTION: SWdefinefield                                                    |
|                                                                             |
|  DESCRIPTION: Defines geolocation or data field within swath structure      |
|                                                                             |
|                                                                             |
|  Return Value    Type     Units     Description                             |
|  ============   ======  =========   =====================================   |
|  status         intn                return status (0) SUCCEED, (-1) FAIL    |
|                                                                             |
|  INPUTS:                                                                    |
|  swathID        int32               swath structure ID                      |
|  fieldtype      char                geo/data fieldtype                      |
|  fieldname      char                fieldname                               |
|  dimlist        char                Dimension list (comma-separated list)   |
|  numbertype     int32               field type                              |
|  merge          int32               merge code                              |
|                                                                             |
|                                                                             |
|  OUTPUTS:                                                                   |
|             None                                                            |
|                                                                             |
|  NOTES:                                                                     |
|                                                                             |
|                                                                             |
|   Date     Programmer   Description                                         |
|  ======   ============  =================================================   |
|  Jun 96   Joel Gales    Original Programmer                                 |
|  Aug 96   Joel Gales    Check name for length                               |
|  Sep 96   Joel Gales    Make string array "dimbuf" dynamic                  |
|  Oct 96   Joel Gales    Make sure total length of "merged" Vdata < 64       |
|  Jun 03   Abe Taaheri   Supplied cast comp_coder_t in call to SDsetcompress |
|                                                                             |
|  END_PROLOG                                                                 |
-----------------------------------------------------------------------------*/
static intn
SWdefinefield(int32 swathID, const char *fieldtype, const char *fieldname, const char *dimlist,
	      int32 numbertype, int32 merge)

{
    intn            i;		/* Loop index */
    intn            status;	/* routine return status variable */
    intn            found;	/* utility found flag */
    intn            foundNT = 0;/* found number type flag */
    intn            foundAllDim = 1;	/* found all dimensions flag */
    intn            first = 1;	/* first entry flag */
    intn            fac;	/* Geo (-1), Data (+1) field factor */
    int32           cnt = 0;

    int32           fid;	/* HDF-EOS file ID */
    int32           vdataID = 0;	/* Vdata ID */
    int32           vgid;	/* Geo/Data field Vgroup ID */
    int32           sdInterfaceID;	/* HDF SDS interface ID */
    int32           sdid;	/* SDS object ID */
    int32           dimid;	/* SDS dimension ID */
    int32           recSize;	/* Vdata record size */
    int32           swVgrpID;	/* Swath root Vgroup ID */
    int32           dims[8];	/* Dimension size array */
    int32           dimsize;	/* Dimension size */
    int32           rank = 0;	/* Field rank */
    int32           slen[32];	/* String length array */
    int32           idOffset = SWIDOFFSET;	/* Swath ID offset */
    int32           compcode;	/* Compression code */
    int32           sID;	/* SwathID - offset */

    uint8          *oneDbuf;	/* Vdata record buffer */
    char           *dimbuf;	/* Dimension buffer */
    char           *comma;	/* Pointer to comma */
    char           *dimcheck;	/* Dimension check buffer */
    char            utlbuf[512];/* Utility buffer */
    char            utlbuf2[256];	/* Utility buffer 2 */
    char           *ptr[32];	/* String pointer array */
    char            swathname[80];	/* Swath name */
    char            errbuf1[128];	/* Error message buffer 1 */
    char            errbuf2[128];	/* Error message buffer 2 */
    char            compparmbuf[128];	/* Compression parameter string buffer */

    const char           *HDFcomp[5] = {"HDFE_COMP_NONE", "HDFE_COMP_RLE",
	"HDFE_COMP_NBIT", "HDFE_COMP_SKPHUFF",
    "HDFE_COMP_DEFLATE"};
    /* Compression code names */

    uint16          good_number[10] = {3, 4, 5, 6, 20, 21, 22, 23, 24, 25};
    /* Valid number types */
    comp_info       c_info;	/* Compression parameter structure */



    /* Setup error message strings */
    /* --------------------------- */
    strcpy(errbuf1, "SWXSDname array too small.\nPlease increase ");
    strcat(errbuf1, "size of HDFE_NAMBUFSIZE in \"HdfEosDef.h\".\n");
    strcpy(errbuf2, "SWXSDdims array too small.\nPlease increase ");
    strcat(errbuf2, "size of HDFE_DIMBUFSIZE in \"HdfEosDef.h\".\n");



    /*
     * Check for proper swath ID and return HDF-EOS file ID, SDinterface ID,
     * and swath root Vgroup ID
     */
    status = SWchkswid(swathID, "SWdefinefield",
		       &fid, &sdInterfaceID, &swVgrpID);


    if (status == 0)
    {
	/* Remove offset from swath ID & get swathname */
	sID = swathID % idOffset;
	Vgetname(swVgrpID, swathname);

	/* Allocate space for dimbuf, copy dimlist into it, & append comma */
	dimbuf = (char *) calloc(strlen(dimlist) + 64, 1);
	if(dimbuf == NULL)
	{ 
	    HEpush(DFE_NOSPACE,"SWdefinefield", __FILE__, __LINE__);
	    return(-1);
	}
	strcpy(dimbuf, dimlist);
	strcat(dimbuf, ",");

	/* Find comma */
	comma = strchr(dimbuf, ',');


	/*
	 * Loop through entries in dimension list to make sure they are
	 * defined in swath
	 */
	while (comma != NULL)
	{
	    /* Copy dimension list entry to dimcheck */
	    dimcheck = (char *) calloc(comma - dimbuf + 1, 1);
	    if(dimcheck == NULL)
	    { 
		HEpush(DFE_NOSPACE,"SWdefinefield", __FILE__, __LINE__);
		free(dimbuf);
		return(-1);
	    }
	    memcpy(dimcheck, dimbuf, comma - dimbuf);

	    /* Get dimension size */
	    dimsize = SWdiminfo(swathID, dimcheck);

	    /* if != -1 then sent found flag, store size and increment rank */
	    if (dimsize != -1)
	    {
		dims[rank] = dimsize;
		rank++;
	    }
	    else
	    {
		/*
		 * If dimension list entry not found - set error return
		 * status, append name to utility buffer for error report
		 */
		status = -1;
		foundAllDim = 0;
		if (first == 1)
		{
		    strcpy(utlbuf, dimcheck);
		}
		else
		{
		    strcat(utlbuf, ",");
		    strcat(utlbuf, dimcheck);
		}
		first = 0;
	    }

	    /*
	     * Go to next dimension entry, find next comma, & free up
	     * dimcheck buffer
	     */
            *comma = '\0';  /* zero out first comma  */
            comma++;
            comma = strchr(comma, ',');
            if (comma != NULL)
            {
               for (i=0; i<(intn)strlen(dimcheck) + 1; i++)
               {
                  dimbuf++;
                  cnt++;
               }
            }
	    free(dimcheck);
	}
        for(i=0; i<cnt; i++)
           dimbuf--;

	free(dimbuf);


	/* Check that UNLIMITED dimension is first dimension if present */
	/* ------------------------------------------------------------ */
	if (status == 0)
	{
	    for (i = 0; i < rank; i++)
	    {
		if (dims[i] == 0 && i != 0)
		{
		    status = -1;
		    HEpush(DFE_GENAPP, "SWdefinefield", __FILE__, __LINE__);
		    HEreport("UNLIMITED dimension must be first dimension.\n");
		}
	    }
	}

	/* Check fieldname length */
	/* ---------------------- */
	if (status == 0)
	{
/* ((intn) strlen(fieldname) > MAX_NC_NAME - 7)
** this was changed because HDF4.1r3 made a change in the
** hlimits.h file.  We have notified NCSA and asked to have 
** it made the same as in previous versions of HDF
** see ncr 26314.  DaW  Apr 2000
*/

	    if (((intn) strlen(fieldname) > VSNAMELENMAX && rank == 1) ||
		((intn) strlen(fieldname) > (256 - 7) && rank > 1))
	    {
		status = -1;
		HEpush(DFE_GENAPP, "SWdefinefield", __FILE__, __LINE__);
		HEreport("Fieldname \"%s\" too long.\n", fieldname);
	    }
	}

	/* Check for valid numbertype */
	/* -------------------------- */
	if (status == 0)
	{
	    for (i = 0; i < 10; i++)
	    {
		if (numbertype == good_number[i])
		{
		    foundNT = 1;
		}
	    }

	    if (foundNT == 0)
	    {
		HEpush(DFE_BADNUMTYPE, "SWdefinefield", __FILE__, __LINE__);
		HEreport("Invalid number type: %d (%s).\n",
			 numbertype, fieldname);
		status = -1;
	    }
	}


	/* Define Field */
	/* ------------ */
	if (status == 0)
	{
	    /* Set factor & get Field Vgroup id */
	    /* -------------------------------- */
	    if (strcmp(fieldtype, "Geolocation Fields") == 0)
	    {
		fac = -1;
		vgid = SWXSwath[sID].VIDTable[0];
	    }
	    else
	    {
		fac = +1;
		vgid = SWXSwath[sID].VIDTable[1];
	    }
	    /*
	     * Note: "fac" is used to distinguish geo fields from data fields
	     * so that they are not merged together
	     */


	    /* One D Fields */
	    /* ------------ */
	    if (rank == 1)
	    {
		/* No Compression for 1D (Vdata) fields */
		compcode = HDFE_COMP_NONE;


		/* If field non-appendable and merge set to AUTOMERGE ... */
		if (dims[0] != 0 && merge == HDFE_AUTOMERGE)
		{
		    i = 0;
		    found = 0;

		    /* Loop through previous entries in 1d combination array */
		    while (SWX1dcomb[3 * i] != 0)
		    {
			/* Get name of previous 1d combined field */
			vdataID = SWX1dcomb[3 * i + 2];
			VSgetname(vdataID, utlbuf);

			/*
			 * If dimension, field type (geo/data), and swath
			 * structure if current entry match a previous entry
			 * and combined name is less than max allowed then
			 * set "found" flag and exit loop
			 */
			if (SWX1dcomb[3 * i] == fac * dims[0] &&
			    SWX1dcomb[3 * i + 1] == swVgrpID &&
			    (intn) strlen(utlbuf) +
			    (intn) strlen(fieldname) + 1 <=
			    VSNAMELENMAX)
			{
			    found = 1;
			    break;
			}
			/* Increment loop index */
			i++;
		    }


		    if (found == 0)
		    {
			/*
			 * If no matching entry found then start new Vdata
			 * and store dimension size, swath root Vgroup ID,
			 * field Vdata and fieldname in external array
			 * "SWX1dcomb"
			 */
			vdataID = VSattach(fid, -1, "w");
			SWX1dcomb[3 * i] = fac * dims[0];
			SWX1dcomb[3 * i + 1] = swVgrpID;
			SWX1dcomb[3 * i + 2] = vdataID;
			VSsetname(vdataID, fieldname);
		    }
		    else
		    {
			/*
			 * If match then concatenate current fieldname to
			 * previous matching fieldnames.
			 */
			strcat(utlbuf, ",");
			strcat(utlbuf, fieldname);
			VSsetname(vdataID, utlbuf);
		    }

		    /* Define field as field within Vdata */
		    VSfdefine(vdataID, fieldname, numbertype, 1);
		    Vinsert(vgid, vdataID);

		}
		else
		{
		    /* 1d No Merge Section */

		    /* Get new vdata ID and establish field within Vdata */
		    vdataID = VSattach(fid, -1, "w");
		    VSsetname(vdataID, fieldname);
		    VSfdefine(vdataID, fieldname, numbertype, 1);
		    VSsetfields(vdataID, fieldname);

		    recSize = VSsizeof(vdataID, (char*) fieldname);
		    if (dims[0] == 0)
		    {
			/*
			 * If appendable field then write single record
			 * filled with 255
			 */
			oneDbuf = (uint8 *) calloc(recSize, 1);
			if(oneDbuf == NULL)
			{ 
			    HEpush(DFE_NOSPACE,"SWdefinefield", __FILE__, __LINE__);
			    return(-1);
			}
			for (i = 0; i < recSize; i++)
			    oneDbuf[i] = 255;
			VSwrite(vdataID, oneDbuf, 1, FULL_INTERLACE);
		    }
		    else
		    {
			/*
			 * If non-appendable then write entire field with
			 * blank records
			 */
			oneDbuf = (uint8 *) calloc(recSize, dims[0]);
			if(oneDbuf == NULL)
			{ 
			    HEpush(DFE_NOSPACE,"SWdefinefield", __FILE__, __LINE__);
			    return(-1);
			}
			VSwrite(vdataID, oneDbuf, dims[0], FULL_INTERLACE);
		    }
		    free(oneDbuf);

		    /* Insert Vdata into field Vgroup & detach */
		    Vinsert(vgid, vdataID);
		    VSdetach(vdataID);

		}		/* End No Merge Section */

	    }			/* End 1d field Section */
	    else
	    {
		/* SDS Interface (Multi-dim fields) */
		/* -------------------------------- */

		/* Get current compression code */
		compcode = SWXSwath[sID].compcode;

		/*
		 * If rank is less than or equal to 3 (and greater than 1)
		 * and AUTOMERGE is set and the first dimension is not
		 * appendable and the compression code is set to none then
		 * ...
		 */
		if (rank <= 3 && merge == HDFE_AUTOMERGE && dims[0] != 0
		    && compcode == HDFE_COMP_NONE)
		{
		    /* Find first empty slot in external combination array */
		    /* --------------------------------------------------- */
		    i = 0;
		    while (SWXSDcomb[5 * i] != 0)
		    {
			i++;
		    }

		    /*
		     * Store dimensions (with geo/data factor), swath root
		     * Vgroup ID, and number type in external combination
		     * array "SWXSDcomb"
		     */

		    if (rank == 2)
		    {
			/* If 2-dim field then set lowest dimension to +/- 1 */
			SWXSDcomb[5 * i] = fac;
			SWXSDcomb[5 * i + 1] = fac * dims[0];
			SWXSDcomb[5 * i + 2] = fac * dims[1];
		    }
		    else
		    {
			SWXSDcomb[5 * i] = fac * dims[0];
			SWXSDcomb[5 * i + 1] = fac * dims[1];
			SWXSDcomb[5 * i + 2] = fac * dims[2];
		    }

		    SWXSDcomb[5 * i + 3] = swVgrpID;
		    SWXSDcomb[5 * i + 4] = numbertype;


		    /* Concatenate fieldname with combined name string */
		    /* ----------------------------------------------- */
		    if ((intn) strlen(SWXSDname) +
			(intn) strlen(fieldname) + 2 < HDFE_NAMBUFSIZE)
		    {
			strcat(SWXSDname, fieldname);
			strcat(SWXSDname, ",");
		    }
		    else
		    {
			/* SWXSDname array too small! */
			/* -------------------------- */
			HEpush(DFE_GENAPP, "SWdefinefield",
			       __FILE__, __LINE__);
			HEreport(errbuf1);
			status = -1;
			return (status);
		    }



		    /*
		     * If 2-dim field then set lowest dimension (in 3-dim
		     * array) to "ONE"
		     */
		    if (rank == 2)
		    {
			if ((intn) strlen(SWXSDdims) + 5 < HDFE_DIMBUFSIZE)
			{
			    strcat(SWXSDdims, "ONE,");
			}
			else
			{
			    /* SWXSDdims array too small! */
			    /* -------------------------- */
			    HEpush(DFE_GENAPP, "SWdefinefield",
				   __FILE__, __LINE__);
			    HEreport(errbuf2);
			    status = -1;
			    return (status);
			}

		    }

		    /*
		     * Concatenate field dimlist to merged dimlist and
		     * separate fields with semi-colon.
		     */
		    if ((intn) strlen(SWXSDdims) +
			(intn) strlen(dimlist) + 2 < HDFE_DIMBUFSIZE)
		    {
			strcat(SWXSDdims, dimlist);
			strcat(SWXSDdims, ";");
		    }
		    else
		    {
			/* SWXSDdims array too small! */
			/* -------------------------- */
			HEpush(DFE_GENAPP, "SWdefinefield",
			       __FILE__, __LINE__);
			HEreport(errbuf2);
			status = -1;
			return (status);
		    }

		}		/* End Multi-Dim Merge Section */
		else
		{
		    /* Multi-Dim No Merge Section */
		    /* ========================== */

		    /* Create SDS dataset */
		    /* ------------------ */
		    sdid = SDcreate(sdInterfaceID, fieldname,
				    numbertype, rank, dims);


		    /* Store Dimension Names in SDS */
		    /* ---------------------------- */
		    rank = EHparsestr(dimlist, ',', ptr, slen);
		    for (i = 0; i < rank; i++)
		    {
			/* Dimension name = Swathname:Dimname */
			memcpy(utlbuf, ptr[i], slen[i]);
			utlbuf[slen[i]] = 0;
			strcat(utlbuf, ":");
			strcat(utlbuf, swathname);

			dimid = SDgetdimid(sdid, i);
			SDsetdimname(dimid, utlbuf);
		    }


		    /* Setup compression parameters */
		    if (compcode == HDFE_COMP_NBIT)
		    {
			c_info.nbit.nt = numbertype;
			c_info.nbit.sign_ext = SWXSwath[sID].compparm[0];
			c_info.nbit.fill_one = SWXSwath[sID].compparm[1];
			c_info.nbit.start_bit = SWXSwath[sID].compparm[2];
			c_info.nbit.bit_len = SWXSwath[sID].compparm[3];
		    }
		    else if (compcode == HDFE_COMP_SKPHUFF)
		    {
			c_info.skphuff.skp_size = (intn) DFKNTsize(numbertype);
		    }
		    else if (compcode == HDFE_COMP_DEFLATE)
		    {
			c_info.deflate.level = SWXSwath[sID].compparm[0];
		    }

		    /* If field is compressed then call SDsetcompress */
		    /* ---------------------------------------------- */
		    if (compcode != HDFE_COMP_NONE)
		    {
                        /* status = */ SDsetcompress(sdid, (comp_coder_t) compcode, &c_info);
		    }


		    /* Attach to Vgroup */
		    /* ---------------- */
		    Vaddtagref(vgid, DFTAG_NDG, SDidtoref(sdid));


		    /* Store SDS dataset IDs */
		    /* --------------------- */
		    if (SWXSwath[sID].nSDS > 0)
		    {
			SWXSwath[sID].sdsID = (int32 *)
			    realloc((void *) SWXSwath[sID].sdsID,
				    (SWXSwath[sID].nSDS + 1) * 4);
			if(SWXSwath[sID].sdsID == NULL)
			{ 
			    HEpush(DFE_NOSPACE,"SWdefinefield", __FILE__, __LINE__);
			    return(-1);
			}

		    }
		    else
		    {
			SWXSwath[sID].sdsID = (int32 *) calloc(1, 4);
			if(SWXSwath[sID].sdsID == NULL)
			{ 
			    HEpush(DFE_NOSPACE,"SWdefinefield", __FILE__, __LINE__);
			    return(-1);
			}
		    }
		    SWXSwath[sID].sdsID[SWXSwath[sID].nSDS] = sdid;
		    SWXSwath[sID].nSDS++;

		}		/* End Multi-Dim No Merge Section */

	    }			/* End Multi-Dim Section */



	    /* Setup metadata string */
	    /* --------------------- */
	    snprintf(utlbuf, sizeof(utlbuf), "%s%s%s", fieldname, ":", dimlist);


	    /* Setup compression metadata */
	    /* -------------------------- */
	    if (compcode != HDFE_COMP_NONE)
	    {
		snprintf(utlbuf2, sizeof(utlbuf2),
			"%s%s",
			":\n\t\t\t\tCompressionType=", HDFcomp[compcode]);

		switch (compcode)
		{
		case HDFE_COMP_NBIT:

		    snprintf(compparmbuf, sizeof(compparmbuf),
			    "%s%d,%d,%d,%d%s",
			    "\n\t\t\t\tCompressionParams=(",
			    SWXSwath[sID].compparm[0],
			    SWXSwath[sID].compparm[1],
			    SWXSwath[sID].compparm[2],
			    SWXSwath[sID].compparm[3], ")");
		    strcat(utlbuf2, compparmbuf);
		    break;


		case HDFE_COMP_DEFLATE:

		    snprintf(compparmbuf, sizeof(compparmbuf),
			    "%s%d",
			    "\n\t\t\t\tDeflateLevel=",
			    SWXSwath[sID].compparm[0]);
		    strcat(utlbuf2, compparmbuf);
		    break;
		}

		/* Concatenate compression parameters with compression code */
		strcat(utlbuf, utlbuf2);
	    }


	    /* Insert field metadata within File Structural Metadata */
	    /* ----------------------------------------------------- */
	    if (strcmp(fieldtype, "Geolocation Fields") == 0)
	    {
		status = EHinsertmeta(sdInterfaceID, swathname, "s", 3L,
				      utlbuf, &numbertype);
	    }
	    else
	    {
		status = EHinsertmeta(sdInterfaceID, swathname, "s", 4L,
				      utlbuf, &numbertype);
	    }

	}
    }

    /* If all dimensions not found then report error */
    /* --------------------------------------------- */
    if (foundAllDim == 0)
    {
	HEpush(DFE_GENAPP, "SWdefinefield", __FILE__, __LINE__);
	HEreport("Dimension(s): \"%s\" not found (%s).\n",
		 utlbuf, fieldname);
	status = -1;
    }

    return (status);
}




/*----------------------------------------------------------------------------|
|  BEGIN_PROLOG                                                               |
|                                                                             |
|  FUNCTION: SWdefgeofield                                                    |
|                                                                             |
|  DESCRIPTION: Defines geolocation field within swath structure (wrapper)    |
|                                                                             |
|                                                                             |
|  Return Value    Type     Units     Description                             |
|  ============   ======  =========   =====================================   |
|  status         intn                return status (0) SUCCEED, (-1) FAIL    |
|                                                                             |
|  INPUTS:                                                                    |
|  swathID        int32               swath structure ID                      |
|  fieldname      char                fieldname                               |
|  dimlist        char                Dimension list (comma-separated list)   |
|  numbertype     int32               field type                              |
|  merge          int32               merge code                              |
|                                                                             |
|  OUTPUTS:                                                                   |
|             None                                                            |
|                                                                             |
|  NOTES:                                                                     |
|                                                                             |
|                                                                             |
|   Date     Programmer   Description                                         |
|  ======   ============  =================================================   |
|  Jun 96   Joel Gales    Original Programmer                                 |
|                                                                             |
|  END_PROLOG                                                                 |
-----------------------------------------------------------------------------*/
intn
SWdefgeofield(int32 swathID, const char *fieldname, const char *dimlist,
	      int32 numbertype, int32 merge)
{
    intn            status;	/* routine return status variable */

    /* Call SWdefinefield routine */
    /* -------------------------- */
    status = SWdefinefield(swathID, "Geolocation Fields", fieldname, dimlist,
			   numbertype, merge);

    return (status);
}




/*----------------------------------------------------------------------------|
|  BEGIN_PROLOG                                                               |
|                                                                             |
|  FUNCTION: SWdefdatafield                                                   |
|                                                                             |
|  DESCRIPTION: Defines data field within swath structure (wrapper)           |
|                                                                             |
|                                                                             |
|  Return Value    Type     Units     Description                             |
|  ============   ======  =========   =====================================   |
|  status         intn                return status (0) SUCCEED, (-1) FAIL    |
|                                                                             |
|  INPUTS:                                                                    |
|  swathID        int32               swath structure ID                      |
|  fieldname      char                fieldname                               |
|  dimlist        char                Dimension list (comma-separated list)   |
|  numbertype     int32               field type                              |
|  merge          int32               merge code                              |
|                                                                             |
|  OUTPUTS:                                                                   |
|             None                                                            |
|                                                                             |
|  NOTES:                                                                     |
|                                                                             |
|                                                                             |
|   Date     Programmer   Description                                         |
|  ======   ============  =================================================   |
|  Jun 96   Joel Gales    Original Programmer                                 |
|                                                                             |
|  END_PROLOG                                                                 |
-----------------------------------------------------------------------------*/
intn
SWdefdatafield(int32 swathID, const char *fieldname, const char *dimlist,
	       int32 numbertype, int32 merge)
{
    intn            status;	/* routine return status variable */

    /* Call SWdefinefield routine */
    /* -------------------------- */
    status = SWdefinefield(swathID, "Data Fields", fieldname, dimlist,
			   numbertype, merge);

    return (status);
}





/*----------------------------------------------------------------------------|
|  BEGIN_PROLOG                                                               |
|                                                                             |
|  FUNCTION: SWwritegeometa                                                   |
|                                                                             |
|  DESCRIPTION: Defines structural metadata for pre-existing geolocation      |
|               field within swath structure                                  |
|                                                                             |
|                                                                             |
|  Return Value    Type     Units     Description                             |
|  ============   ======  =========   =====================================   |
|  status         intn                return status (0) SUCCEED, (-1) FAIL    |
|                                                                             |
|  INPUTS:                                                                    |
|  swathID        int32               swath structure ID                      |
|  fieldname      char                fieldname                               |
|  dimlist        char                Dimension list (comma-separated list)   |
|  numbertype     int32               field type                              |
|                                                                             |
|                                                                             |
|  OUTPUTS:                                                                   |
|             None                                                            |
|                                                                             |
|  NOTES:                                                                     |
|                                                                             |
|                                                                             |
|   Date     Programmer   Description                                         |
|  ======   ============  =================================================   |
|  Jun 96   Joel Gales    Original Programmer                                 |
|                                                                             |
|  END_PROLOG                                                                 |
-----------------------------------------------------------------------------*/
intn
SWwritegeometa(int32 swathID, const char *fieldname, const char *dimlist,
	       int32 numbertype)
{
    intn            status = 0;	/* routine return status variable */

    int32           sdInterfaceID;	/* HDF SDS interface ID */
    int32           dum;	/* dummy variable */
    int32           idOffset = SWIDOFFSET;	/* Swath ID offset */

    char            utlbuf[256];/* Utility buffer */
    char            swathname[80];	/* Swath name */

    status = SWchkswid(swathID, "SWwritegeometa", &dum, &sdInterfaceID,
		       &dum);

    if (status == 0)
    {
	/* Setup and write field metadata */
	/* ------------------------------ */
	snprintf(utlbuf, sizeof(utlbuf), "%s%s%s", fieldname, ":", dimlist);

	Vgetname(SWXSwath[swathID % idOffset].IDTable, swathname);
	status = EHinsertmeta(sdInterfaceID, swathname, "s", 3L,
			      utlbuf, &numbertype);
    }

    return (status);
}




/*----------------------------------------------------------------------------|
|  BEGIN_PROLOG                                                               |
|                                                                             |
|  FUNCTION: SWwritedatameta                                                  |
|                                                                             |
|  DESCRIPTION: Defines structural metadata for pre-existing data             |
|               field within swath structure                                  |
|                                                                             |
|                                                                             |
|  Return Value    Type     Units     Description                             |
|  ============   ======  =========   =====================================   |
|  status         intn                return status (0) SUCCEED, (-1) FAIL    |
|                                                                             |
|  INPUTS:                                                                    |
|  swathID        int32               swath structure ID                      |
|  fieldname      char                fieldname                               |
|  dimlist        char                Dimension list (comma-separated list)   |
|  numbertype     int32               field type                              |
|                                                                             |
|                                                                             |
|  OUTPUTS:                                                                   |
|             None                                                            |
|                                                                             |
|  NOTES:                                                                     |
|                                                                             |
|                                                                             |
|   Date     Programmer   Description                                         |
|  ======   ============  =================================================   |
|  Jun 96   Joel Gales    Original Programmer                                 |
|                                                                             |
|  END_PROLOG                                                                 |
-----------------------------------------------------------------------------*/
intn
SWwritedatameta(int32 swathID, const char *fieldname, const char *dimlist,
		int32 numbertype)
{
    intn            status = 0;	/* routine return status variable */

    int32           sdInterfaceID;	/* HDF SDS interface ID */
    int32           dum;	/* dummy variable */
    int32           idOffset = SWIDOFFSET;	/* Swath ID offset */

    char            utlbuf[256];/* Utility buffer */
    char            swathname[80];	/* Swath name */

    status = SWchkswid(swathID, "SWwritedatameta", &dum, &sdInterfaceID,
		       &dum);

    if (status == 0)
    {
	/* Setup and write field metadata */
	/* ------------------------------ */
	snprintf(utlbuf, sizeof(utlbuf), "%s%s%s", fieldname, ":", dimlist);

	Vgetname(SWXSwath[swathID % idOffset].IDTable, swathname);
	status = EHinsertmeta(sdInterfaceID, swathname, "s", 4L,
			      utlbuf, &numbertype);
    }
    return (status);
}



/*----------------------------------------------------------------------------|
|  BEGIN_PROLOG                                                               |
|                                                                             |
|  FUNCTION: SWwrrdattr                                                       |
|                                                                             |
|  DESCRIPTION:                                                               |
|                                                                             |
|                                                                             |
|  Return Value    Type     Units     Description                             |
|  ============   ======  =========   =====================================   |
|  status         intn                return status (0) SUCCEED, (-1) FAIL    |
|                                                                             |
|  INPUTS:                                                                    |
|  swathID        int32               swath structure ID                      |
|  attrname       char                attribute name                          |
|  numbertype     int32               attribute HDF numbertype                |
|  count          int32               Number of attribute elements            |
|  wrcode         char                Read/Write Code "w/r"                   |
|  datbuf         void                I/O buffer                              |
|                                                                             |
|  OUTPUTS:                                                                   |
|  datbuf                                                                     |
|                                                                             |
|  NOTES:                                                                     |
|                                                                             |
|                                                                             |
|   Date     Programmer   Description                                         |
|  ======   ============  =================================================   |
|  Jun 96   Joel Gales    Original Programmer                                 |
|  Oct 96   Joel Gales    Get Attribute Vgroup ID from external array         |
|                                                                             |
|  END_PROLOG                                                                 |
-----------------------------------------------------------------------------*/
static intn
SWwrrdattr(int32 swathID, const char *attrname, int32 numbertype, int32 count,
	   const char *wrcode, VOIDP datbuf)

{
    intn            status;	/* routine return status variable */

    int32           fid;	/* HDF-EOS file ID */
    int32           attrVgrpID;	/* Swath attribute ID */
    int32           dum;	/* dummy variable */
    int32           idOffset = SWIDOFFSET;	/* Swath ID offset */

    /* Check Swath id */
    status = SWchkswid(swathID, "SWwrrdattr", &fid, &dum, &dum);

    if (status == 0)
    {
	/* Get attribute Vgroup ID and call EHattr to perform I/O */
	/* ------------------------------------------------------ */
	attrVgrpID = SWXSwath[swathID % idOffset].VIDTable[2];
	status = EHattr(fid, attrVgrpID, attrname, numbertype, count,
			wrcode, datbuf);
    }
    return (status);
}



/*----------------------------------------------------------------------------|
|  BEGIN_PROLOG                                                               |
|                                                                             |
|  FUNCTION: SWwriteattr                                                      |
|                                                                             |
|  DESCRIPTION: Writes/updates attribute in a swath.                          |
|                                                                             |
|                                                                             |
|  Return Value    Type     Units     Description                             |
|  ============   ======  =========   =====================================   |
|  status         intn                return status (0) SUCCEED, (-1) FAIL    |
|                                                                             |
|  INPUTS:                                                                    |
|  swathID        int32               swath structure ID                      |
|  attrname       char                attribute name                          |
|  numbertype     int32               attribute HDF numbertype                |
|  count          int32               Number of attribute elements            |
|  datbuf         void                I/O buffer                              |
|                                                                             |
|  OUTPUTS:                                                                   |
|             None                                                            |
|                                                                             |
|  NOTES:                                                                     |
|                                                                             |
|                                                                             |
|   Date     Programmer   Description                                         |
|  ======   ============  =================================================   |
|  Jun 96   Joel Gales    Original Programmer                                 |
|                                                                             |
|  END_PROLOG                                                                 |
-----------------------------------------------------------------------------*/
intn
SWwriteattr(int32 swathID, const char *attrname, int32 numbertype, int32 count,
	    VOIDP datbuf)
{
    intn            status = 0;	/* routine return status variable */

    /* Call SWwrrdattr routine to write attribute */
    /* ------------------------------------------ */
    status = SWwrrdattr(swathID, attrname, numbertype, count, "w", datbuf);

    return (status);
}



/*----------------------------------------------------------------------------|
|  BEGIN_PROLOG                                                               |
|                                                                             |
|  FUNCTION: SWreadattr                                                       |
|                                                                             |
|  DESCRIPTION: Reads attribute from a swath.                                 |
|                                                                             |
|                                                                             |
|  Return Value    Type     Units     Description                             |
|  ============   ======  =========   =====================================   |
|  status         intn                return status (0) SUCCEED, (-1) FAIL    |
|                                                                             |
|  INPUTS:                                                                    |
|  swathID        int32               swath structure ID                      |
|  attrname       char                attribute name                          |
|                                                                             |
|  OUTPUTS:                                                                   |
|  datbuf         void                I/O buffer                              |
|                                                                             |
|  NOTES:                                                                     |
|                                                                             |
|                                                                             |
|   Date     Programmer   Description                                         |
|  ======   ============  =================================================   |
|  Jun 96   Joel Gales    Original Programmer                                 |
|                                                                             |
|  END_PROLOG                                                                 |
-----------------------------------------------------------------------------*/
intn
SWreadattr(int32 swathID, const char *attrname, VOIDP datbuf)
{
    intn            status = 0;	/* routine return status variable */
    int32           dum = 0;	/* dummy variable */

    /* Call SWwrrdattr routine to read attribute */
    /* ----------------------------------------- */
    status = SWwrrdattr(swathID, attrname, dum, dum, "r", datbuf);

    return (status);
}





/*----------------------------------------------------------------------------|
|  BEGIN_PROLOG                                                               |
|                                                                             |
|  FUNCTION: SWattrinfo                                                       |
|                                                                             |
|  DESCRIPTION:                                                               |
|                                                                             |
|                                                                             |
|  Return Value    Type     Units     Description                             |
|  ============   ======  =========   =====================================   |
|  status         intn                return status (0) SUCCEED, (-1) FAIL    |
|                                                                             |
|  INPUTS:                                                                    |
|  swathID        int32               swath structure ID                      |
|  attrname       char                attribute name                          |
|                                                                             |
|  OUTPUTS:                                                                   |
|  numbertype     int32               attribute HDF numbertype                |
|  count          int32               Number of attribute elements            |
|                                                                             |
|                                                                             |
|  OUTPUTS:                                                                   |
|             None                                                            |
|                                                                             |
|  NOTES:                                                                     |
|                                                                             |
|                                                                             |
|   Date     Programmer   Description                                         |
|  ======   ============  =================================================   |
|  Jun 96   Joel Gales    Original Programmer                                 |
|  Oct 96   Joel Gales    Get Attribute Vgroup ID from external array         |
|                                                                             |
|  END_PROLOG                                                                 |
-----------------------------------------------------------------------------*/
intn
SWattrinfo(int32 swathID, const char *attrname, int32 * numbertype, int32 * count)
{
    intn            status = 0;	/* routine return status variable */

    int32           fid;	/* HDF-EOS file ID */
    int32           attrVgrpID;	/* Swath attribute ID */
    int32           dum;	/* dummy variable */
    int32           idOffset = SWIDOFFSET;	/* Swath ID offset */

    /* Check for valid swath ID */
    /* ------------------------ */
    status = SWchkswid(swathID, "SWattrinfo", &fid, &dum, &dum);

    if (status == 0)
    {
	/* Get attribute Vgroup ID and call EHattrinfo */
	/* ------------------------------------------- */
	attrVgrpID = SWXSwath[swathID % idOffset].VIDTable[2];

	status = EHattrinfo(fid, attrVgrpID, attrname, numbertype,
			    count);
    }
    return (status);
}






/*----------------------------------------------------------------------------|
|  BEGIN_PROLOG                                                               |
|                                                                             |
|  FUNCTION: SWinqattrs                                                       |
|                                                                             |
|  DESCRIPTION:                                                               |
|                                                                             |
|                                                                             |
|  Return Value    Type     Units     Description                             |
|  ============   ======  =========   =====================================   |
|  nattr          int32               Number of attributes in swath struct    |
|                                                                             |
|  INPUTS:                                                                    |
|  swath ID       int32               swath structure ID                      |
|                                                                             |
|  OUTPUTS:                                                                   |
|  attrnames      char                Attribute names in swath struct         |
|                                     (Comma-separated list)                  |
|  strbufsize     int32               Attributes name list string length      |
|                                                                             |
|  OUTPUTS:                                                                   |
|             None                                                            |
|                                                                             |
|  NOTES:                                                                     |
|                                                                             |
|                                                                             |
|   Date     Programmer   Description                                         |
|  ======   ============  =================================================   |
|  Jun 96   Joel Gales    Original Programmer                                 |
|  Oct 96   Joel Gales    Initialize nattr                                    |
|  Oct 96   Joel Gales    Get Attribute Vgroup ID from external array         |
|                                                                             |
|  END_PROLOG                                                                 |
-----------------------------------------------------------------------------*/
int32
SWinqattrs(int32 swathID, char *attrnames, int32 * strbufsize)
{
    intn            status;	/* routine return status variable */

    int32           fid;	/* HDF-EOS file ID */
    int32           attrVgrpID;	/* Swath attribute ID */
    int32           dum;	/* dummy variable */
    int32           nattr = 0;	/* Number of attributes */
    int32           idOffset = SWIDOFFSET;	/* Swath ID offset */

    /* Check Swath id */
    status = SWchkswid(swathID, "SWinqattrs", &fid, &dum, &dum);

    if (status == 0)
    {
	/* Get attribute Vgroup ID and call EHattrcat */
	/* ------------------------------------------ */
	attrVgrpID = SWXSwath[swathID % idOffset].VIDTable[2];

	nattr = EHattrcat(fid, attrVgrpID, attrnames, strbufsize);
    }

    return (nattr);
}

#define REMQUOTE \
\
memmove(utlstr, utlstr + 1, strlen(utlstr) - 2); \
utlstr[strlen(utlstr) - 2] = 0;


/*----------------------------------------------------------------------------|
|  BEGIN_PROLOG                                                               |
|                                                                             |
|  FUNCTION: SWinqdims                                                        |
|                                                                             |
|  DESCRIPTION: Returns dimension names and values defined in swath structure |
|                                                                             |
|                                                                             |
|  Return Value    Type     Units     Description                             |
|  ============   ======  =========   =====================================   |
|  nDim           int32               Number of defined dimensions            |
|                                                                             |
|  INPUTS:                                                                    |
|  swathID        int32               swath structure ID                      |
|                                                                             |
|  OUTPUTS:                                                                   |
|  dimnames       char                Dimension names (comma-separated)       |
|  dims           int32               Dimension values                        |
|                                                                             |
|  NOTES:                                                                     |
|                                                                             |
|                                                                             |
|   Date     Programmer   Description                                         |
|  ======   ============  =================================================   |
|  Jun 96   Joel Gales    Original Programmer                                 |
|  Aug 96   Joel Gales    Make metadata ODL compliant                         |
|  Feb 97   Joel Gales    Set nDim to -1 if status = -1                       |
|                                                                             |
|  END_PROLOG                                                                 |
-----------------------------------------------------------------------------*/
int32
SWinqdims(int32 swathID, char *dimnames, int32 dims[])

{
    intn            status;	/* routine return status variable */

    int32           fid;	/* HDF-EOS file ID */
    int32           sdInterfaceID;	/* HDF SDS interface ID */
    int32           swVgrpID;	/* Swath root Vgroup ID */
    int32           size;	/* Dimension size */
    int32           idOffset = SWIDOFFSET;	/* Swath ID offset */
    int32           nDim = 0;	/* Number of dimensions */

    char           *metabuf;	/* Pointer to structural metadata (SM) */
    char           *metaptrs[2];/* Pointers to begin and end of SM section */
    char            swathname[80];	/* Swath Name */
    char           *utlstr;     /* Utility string */


    /* Allocate space for utility string */
    /* --------------------------------- */
    utlstr = (char *) calloc(UTLSTR_MAX_SIZE, sizeof(char));
    if(utlstr == NULL)
    { 
	HEpush(DFE_NOSPACE,"SWinqdims", __FILE__, __LINE__);
	return(-1);
    }

    /* Check for valid swath id */
    status = SWchkswid(swathID, "SWinqdims", &fid, &sdInterfaceID, &swVgrpID);

    if (status == 0)
    {
	/* If dimension names or sizes are desired ... */
	/* ------------------------------------------- */
	if (dimnames != NULL || dims != NULL)
	{
	    /* Get swath name */
	    Vgetname(SWXSwath[swathID % idOffset].IDTable, swathname);

	    /* Get pointers to "Dimension" section within SM */
	    metabuf = (char *) EHmetagroup(sdInterfaceID, swathname, "s",
					   "Dimension", metaptrs);
	    if(metabuf == NULL)
	    {
		free(utlstr);
		return(-1);
	    }
	    /* If dimension names are desired then "clear" name buffer */
	    if (dimnames != NULL)
	    {
		dimnames[0] = 0;
	    }


	    /* Begin loop through dimension entries in metadata */
	    /* ------------------------------------------------ */
	    while (1)
	    {
		/* Search for OBJECT string */
		metaptrs[0] = strstr(metaptrs[0], "\t\tOBJECT=");

		/* If found within "Dimension" metadata section ... */
		if (metaptrs[0] < metaptrs[1] && metaptrs[0] != NULL)
		{
		    /* Get Dimension Name (if desired) */
		    if (dimnames != NULL)
		    {
			/* Check 1st for old meta data then new */
			/* ------------------------------------ */
			EHgetmetavalue(metaptrs, "OBJECT", utlstr);

			/*
			 * If OBJECT value begins with double quote then old
			 * metadata, dimension name is OBJECT value.
			 * Otherwise search for "DimensionName" string
			 */
			if (utlstr[0] != '"')
			{
			    metaptrs[0] =
				strstr(metaptrs[0], "\t\t\t\tDimensionName=");
			    EHgetmetavalue(metaptrs, "DimensionName", utlstr);
			}

			/* Strip off double quotes */
			/* ----------------------- */
			REMQUOTE

			/* If not first name then add comma delimiter */
			    if (nDim > 0)
			{
			    strcat(dimnames, ",");
			}
			/* Add dimension name to dimension list */
			strcat(dimnames, utlstr);
		    }

		    /* Get Dimension Size (if desired) */
		    if (dims != NULL)
		    {
			EHgetmetavalue(metaptrs, "Size", utlstr);
			size = atoi(utlstr);
			dims[nDim] = size;
		    }
		    /* Increment number of dimensions */
		    nDim++;
		}
		else
		    /* No more dimensions found */
		{
		    break;
		}
	    }
	    free(metabuf);
	}
    }


    /* Set nDim to -1 if error status exists */
    /* ------------------------------------- */
    if (status == -1)
    {
	nDim = -1;
    }
    free(utlstr);

    return (nDim);
}





/*----------------------------------------------------------------------------|
|  BEGIN_PROLOG                                                               |
|                                                                             |
|  FUNCTION: SWinqmaps                                                        |
|                                                                             |
|  DESCRIPTION: Returns dimension mappings and offsets and increments         |
|                                                                             |
|                                                                             |
|  Return Value    Type     Units     Description                             |
|  ============   ======  =========   =====================================   |
|  nMap           int32               Number of dimension mappings            |
|                                                                             |
|  INPUTS:                                                                    |
|  swathID        int32               swath structure ID                      |
|                                                                             |
|  OUTPUTS:                                                                   |
|  dimmaps        char                dimension mappings (comma-separated)    |
|  offset         int32               array of offsets                        |
|  increment      int32               array of increments                     |
|                                                                             |
|  NOTES:                                                                     |
|                                                                             |
|                                                                             |
|   Date     Programmer   Description                                         |
|  ======   ============  =================================================   |
|  Jun 96   Joel Gales    Original Programmer                                 |
|  Aug 96   Joel Gales    Make metadata ODL compliant                         |
|  Feb 97   Joel Gales    Set nMap to -1 if status = -1                       |
|                                                                             |
|  END_PROLOG                                                                 |
-----------------------------------------------------------------------------*/
int32
SWinqmaps(int32 swathID, char *dimmaps, int32 offset[], int32 increment[])

{
    intn            status;	/* routine return status variable */

    int32           fid;	/* HDF-EOS file ID */
    int32           sdInterfaceID;	/* HDF SDS interface ID */
    int32           swVgrpID;	/* Swath root Vgroup ID */
    int32           off;	/* Mapping Offset */
    int32           incr;	/* Mapping Increment */
    int32           idOffset = SWIDOFFSET;	/* Swath ID offset */
    int32           nMap = 0;	/* Number of mappings */

    char           *metabuf;	/* Pointer to structural metadata (SM) */
    char           *metaptrs[2];/* Pointers to begin and end of SM section */
    char            swathname[80];	/* Swath Name */
    char           *utlstr;     /* Utility string */


    /* Allocate space for utility string */
    /* --------------------------------- */
    utlstr = (char *) calloc(UTLSTR_MAX_SIZE, sizeof(char));
    if(utlstr == NULL)
    { 
	HEpush(DFE_NOSPACE,"SWinqmaps", __FILE__, __LINE__);
	return(-1);
    }

    /* Check for valid swath id */
    status = SWchkswid(swathID, "SWinqmaps", &fid, &sdInterfaceID, &swVgrpID);
    if (status == 0)
    {
	/* If mapping names or offsets or increments desired ... */
	/* ----------------------------------------------------- */
	if (dimmaps != NULL || offset != NULL || increment != NULL)
	{

	    /* Get swath name */
	    Vgetname(SWXSwath[swathID % idOffset].IDTable, swathname);

	    /* Get pointers to "DimensionMap" section within SM */
	    metabuf = (char *) EHmetagroup(sdInterfaceID, swathname, "s",
					   "DimensionMap", metaptrs);
	    if(metabuf == NULL)
	    {
		free(utlstr);
		return(-1);
	    }
	    /* If mapping names are desired then "clear" name buffer */
	    if (dimmaps != NULL)
	    {
		dimmaps[0] = 0;
	    }

	    /* Begin loop through mapping entries in metadata */
	    /* ---------------------------------------------- */
	    while (1)
	    {
		/* Search for OBJECT string */
		metaptrs[0] = strstr(metaptrs[0], "\t\tOBJECT=");

		/* If found within "DimensionMap" metadata section ... */
		if (metaptrs[0] < metaptrs[1] && metaptrs[0] != NULL)
		{
		    /* Get Geo & Data Dimensions (if desired) */
		    if (dimmaps != NULL)
		    {
			/* Get Geo Dim, remove quotes, add "/" */
			EHgetmetavalue(metaptrs, "GeoDimension", utlstr);
			REMQUOTE
			    strcat(utlstr, "/");

			/* If not first map then add comma delimiter. */
			if (nMap > 0)
			{
			    strcat(dimmaps, ",");
			}

			/* Add to map list */
			strcat(dimmaps, utlstr);

			/* Get Data Dim, remove quotes */
			EHgetmetavalue(metaptrs, "DataDimension", utlstr);
			REMQUOTE

			/* Add to map list */
			    strcat(dimmaps, utlstr);
		    }

		    /* Get Offset (if desired) */
		    if (offset != NULL)
		    {
			EHgetmetavalue(metaptrs, "Offset", utlstr);
			off = atoi(utlstr);
			offset[nMap] = off;
		    }

		    /* Get Increment (if desired) */
		    if (increment != NULL)
		    {
			EHgetmetavalue(metaptrs, "Increment", utlstr);
			incr = atoi(utlstr);
			increment[nMap] = incr;
		    }

		    /* Increment number of maps */
		    nMap++;
		}
		else
		    /* No more mappings found */
		{
		    break;
		}
	    }
	    free(metabuf);
	}
    }


    /* Set nMap to -1 if error status exists */
    /* ------------------------------------- */
    if (status == -1)
    {
	nMap = -1;
    }
    free(utlstr);

    return (nMap);
}





/*----------------------------------------------------------------------------|
|  BEGIN_PROLOG                                                               |
|                                                                             |
|  FUNCTION: SWinqidxmaps                                                     |
|                                                                             |
|  DESCRIPTION: Returns l_indexed mappings and l_index sizes                      |
|                                                                             |
|                                                                             |
|  Return Value    Type     Units     Description                             |
|  ============   ======  =========   =====================================   |
|  nMap           int32               Number of l_indexed dimension mappings    |
|                                                                             |
|  INPUTS:                                                                    |
|  swathID        int32               swath structure ID                      |
|                                                                             |
|  OUTPUTS:                                                                   |
|  idxmaps        char                l_indexed dimension mappings              |
|                                     (comma-separated)                       |
|  idxsizes       int32               Number of elements in each mapping      |
|                                                                             |
|                                                                             |
|  NOTES:                                                                     |
|                                                                             |
|                                                                             |
|   Date     Programmer   Description                                         |
|  ======   ============  =================================================   |
|  Jun 96   Joel Gales    Original Programmer                                 |
|  Aug 96   Joel Gales    Make metadata ODL compliant                         |
|  Feb 97   Joel Gales    Set nMap to -1 if status = -1                       |
|                                                                             |
|  END_PROLOG                                                                 |
-----------------------------------------------------------------------------*/
int32
SWinqidxmaps(int32 swathID, char *idxmaps, int32 idxsizes[])

{
    intn            status;	/* routine return status variable */

    int32           fid;	/* HDF-EOS file ID */
    int32           sdInterfaceID;	/* HDF SDS interface ID */
    int32           swVgrpID;	/* Swath root Vgroup ID */
    int32           idOffset = SWIDOFFSET;	/* Swath ID offset */
    int32           nMap = 0;	/* Number of mappings */

    char           *metabuf;	/* Pointer to structural metadata (SM) */
    char           *metaptrs[2];/* Pointers to begin and end of SM section */
    char            swathname[80];	/* Swath Name */
    char           *utlstr;     /* Utility string */
    char           *slash;	/* Pointer to slash */


    /* Allocate space for utility string */
    /* --------------------------------- */
    utlstr = (char *) calloc(UTLSTR_MAX_SIZE, sizeof(char));
    if(utlstr == NULL)
    { 
	HEpush(DFE_NOSPACE,"SWinqidxmaps", __FILE__, __LINE__);
	return(-1);
    }
    /* Check for valid swath id */
    status = SWchkswid(swathID, "SWinqidxmaps", &fid,
		       &sdInterfaceID, &swVgrpID);

    if (status == 0)
    {
	/* If mapping names or l_index sizes desired ... */
	/* ------------------------------------------- */
	if (idxmaps != NULL || idxsizes != NULL)
	{
	    /* Get swath name */
	    Vgetname(SWXSwath[swathID % idOffset].IDTable, swathname);

	    /* Get pointers to "IndexDimensionMap" section within SM */
	    metabuf = (char *) EHmetagroup(sdInterfaceID, swathname, "s",
					   "IndexDimensionMap", metaptrs);
	    if(metabuf == NULL)
	    {
		free(utlstr);
		return(-1);
	    }
	    /* If mapping names are desired then "clear" name buffer */
	    if (idxmaps != NULL)
	    {
		idxmaps[0] = 0;
	    }

	    /* Begin loop through mapping entries in metadata */
	    /* ---------------------------------------------- */
	    while (1)
	    {
		/* Search for OBJECT string */
		metaptrs[0] = strstr(metaptrs[0], "\t\tOBJECT=");

		/* If found within "IndexDimensionMap" metadata section ... */
		if (metaptrs[0] < metaptrs[1] && metaptrs[0] != NULL)
		{
		    /* Get Geo & Data Dimensions and # of indices */
		    if (idxmaps != NULL)
		    {
			/* Get Geo Dim, remove quotes, add "/" */
			EHgetmetavalue(metaptrs, "GeoDimension", utlstr);
			REMQUOTE
			    strcat(utlstr, "/");

			/* If not first map then add comma delimiter. */
			if (nMap > 0)
			{
			    strcat(idxmaps, ",");
			}

			/* Add to map list */
			strcat(idxmaps, utlstr);


			/* Get Index size (if desired) */
			if (idxsizes != NULL)
			{
			    /* Parse off geo dimension and find its size */
			    slash = strchr(utlstr, '/');
			    *slash = 0;
			    idxsizes[nMap] = SWdiminfo(swathID, utlstr);
			}


			/* Get Data Dim, remove quotes */
			EHgetmetavalue(metaptrs, "DataDimension", utlstr);
			REMQUOTE

			/* Add to map list */
			    strcat(idxmaps, utlstr);
		    }

		    /* Increment number of maps */
		    nMap++;
		}
		else
		    /* No more mappings found */
		{
		    break;
		}
	    }
	    free(metabuf);
	}
    }


    /* Set nMap to -1 if error status exists */
    /* ------------------------------------- */
    if (status == -1)
    {
	nMap = -1;
    }
    free(utlstr);

    return (nMap);
}




/*----------------------------------------------------------------------------|
|  BEGIN_PROLOG                                                               |
|                                                                             |
|  FUNCTION: SWinqfields                                                      |
|                                                                             |
|  DESCRIPTION: Returns fieldnames, ranks and numbertypes defined in swath.   |
|                                                                             |
|                                                                             |
|  Return Value    Type     Units     Description                             |
|  ============   ======  =========   =====================================   |
|  nFld           int32               Number of (geo/data) fields in swath    |
|                                                                             |
|  INPUTS:                                                                    |
|  swathID        int32               swath structure ID                      |
|  fieldtype      char                field type (geo or data)                |
|                                                                             |
|                                                                             |
|  OUTPUTS:                                                                   |
|  fieldlist      char                Field names (comma-separated)           |
|  rank           int32               Array of ranks                          |
|  numbertype     int32               Array of HDF number types               |
|                                                                             |
|  NOTES:                                                                     |
|                                                                             |
|                                                                             |
|   Date     Programmer   Description                                         |
|  ======   ============  =================================================   |
|  Jun 96   Joel Gales    Original Programmer                                 |
|  Aug 96   Joel Gales    Make metadata ODL compliant                         |
|  Feb 97   Joel Gales    Set nFld to -1 if status = -1                       |
|                                                                             |
|  END_PROLOG                                                                 |
-----------------------------------------------------------------------------*/
static int32
SWinqfields(int32 swathID, const char *fieldtype, char *fieldlist, int32 rank[],
	    int32 numbertype[])

{
    intn            status;	/* routine return status variable */

    int32           fid;	/* HDF-EOS file ID */
    int32           sdInterfaceID;	/* HDF SDS interface ID */
    int32           swVgrpID;	/* Swath root Vgroup ID */
    int32           idOffset = SWIDOFFSET;	/* Swath ID offset */
    int32           nFld = 0;	/* Number of mappings */
    int32           slen[8];	/* String length array */

    char           *metabuf;	/* Pointer to structural metadata (SM) */
    char           *metaptrs[2];/* Pointers to begin and end of SM section */
    char            swathname[80];	/* Swath Name */
    char           *utlstr;	/* Utility string */
    char           *utlstr2;	/* Utility string 2 */
    char           *ptr[8];	/* String pointer array */


    /* Allocate space for utility string */
    /* --------------------------------- */
    utlstr = (char *) calloc(UTLSTR_MAX_SIZE, sizeof(char));
    if(utlstr == NULL)
    { 
	HEpush(DFE_NOSPACE,"SWinqfields", __FILE__, __LINE__);
	return(-1);
    }

    utlstr2 = (char *) calloc(UTLSTR_MAX_SIZE, sizeof(char));
    if(utlstr2 == NULL)
    { 
	HEpush(DFE_NOSPACE,"SWinqfields", __FILE__, __LINE__);
	free(utlstr);
	return(-1);
    }

    /* Check for valid swath id */
    status = SWchkswid(swathID, "SWinqfields",
		       &fid, &sdInterfaceID, &swVgrpID);

    if (status == 0)
    {
	/* If field names, ranks,  or number types desired ... */
	/* --------------------------------------------------- */
	if (fieldlist != NULL || rank != NULL || numbertype != NULL)
	{
	    /* Get swath name */
	    Vgetname(SWXSwath[swathID % idOffset].IDTable, swathname);

	    /* Get pointers to "GeoField" or "DataField" section within SM */
	    if (strcmp(fieldtype, "Geolocation Fields") == 0)
	    {
		metabuf = (char *) EHmetagroup(sdInterfaceID, swathname, "s",
					       "GeoField", metaptrs);
		if(metabuf == NULL)
		{
		    free(utlstr);
		    free(utlstr2);
		    return(-1);
		}
		strcpy(utlstr2, "GeoFieldName");
	    }
	    else
	    {
		metabuf = (char *) EHmetagroup(sdInterfaceID, swathname, "s",
					       "DataField", metaptrs);
		if(metabuf == NULL)
		{
		    free(utlstr);
		    free(utlstr2);
		    return(-1);
		}
		strcpy(utlstr2, "DataFieldName");
	    }


	    /* If field names are desired then "clear" name buffer */
	    if (fieldlist != NULL)
	    {
		fieldlist[0] = 0;
	    }


	    /* Begin loop through mapping entries in metadata */
	    /* ---------------------------------------------- */
	    while (1)
	    {
		/* Search for OBJECT string */
		metaptrs[0] = strstr(metaptrs[0], "\t\tOBJECT=");

		/* If found within "Geo" or "Data" Field metadata section .. */
		if (metaptrs[0] < metaptrs[1] && metaptrs[0] != NULL)
		{
		    /* Get Fieldnames (if desired) */
		    if (fieldlist != NULL)
		    {
			/* Check 1st for old meta data then new */
			/* ------------------------------------ */
			EHgetmetavalue(metaptrs, "OBJECT", utlstr);

			/*
			 * If OBJECT value begins with double quote then old
			 * metadata, field name is OBJECT value. Otherwise
			 * search for "GeoFieldName" or "DataFieldName"
			 * string
			 */

			if (utlstr[0] != '"')
			{
			    strcpy(utlstr, "\t\t\t\t");
			    strcat(utlstr, utlstr2);
			    strcat(utlstr, "=");
			    metaptrs[0] = strstr(metaptrs[0], utlstr);
			    EHgetmetavalue(metaptrs, utlstr2, utlstr);
			}

			/* Strip off double quotes */
			/* ----------------------- */
			REMQUOTE


			/* Add to fieldlist */
			/* ---------------- */
			    if (nFld > 0)
			{
			    strcat(fieldlist, ",");
			}
			strcat(fieldlist, utlstr);

		    }
		    /* Get Numbertype */
		    if (numbertype != NULL)
		    {
			EHgetmetavalue(metaptrs, "DataType", utlstr);
			numbertype[nFld] = EHnumstr(utlstr);
		    }
		    /*
		     * Get Rank (if desired) by counting # of dimensions in
		     * "DimList" string
		     */
		    if (rank != NULL)
		    {
			EHgetmetavalue(metaptrs, "DimList", utlstr);
			rank[nFld] = EHparsestr(utlstr, ',', ptr, slen);
		    }
		    /* Increment number of fields */
		    nFld++;
		}
		else
		    /* No more fields found */
		{
		    break;
		}
	    }
	    free(metabuf);
	}
    }

    /* Set nFld to -1 if error status exists */
    /* ------------------------------------- */
    if (status == -1)
    {
	nFld = -1;
    }

    free(utlstr);
    free(utlstr2);

    return (nFld);
}




/*----------------------------------------------------------------------------|
|  BEGIN_PROLOG                                                               |
|                                                                             |
|  FUNCTION: SWinqgeofields                                                   |
|                                                                             |
|  DESCRIPTION: Inquires about geo fields in swath                            |
|                                                                             |
|                                                                             |
|  Return Value    Type     Units     Description                             |
|  ============   ======  =========   =====================================   |
|  nflds          int32               Number of geo fields in swath           |
|                                                                             |
|  INPUTS:                                                                    |
|  swathID        int32               swath structure ID                      |
|                                                                             |
|  OUTPUTS:                                                                   |
|  fieldlist      char                Field names (comma-separated)           |
|  rank           int32               Array of ranks                          |
|  numbertype     int32               Array of HDF number types               |
|                                                                             |
|  NOTES:                                                                     |
|                                                                             |
|                                                                             |
|   Date     Programmer   Description                                         |
|  ======   ============  =================================================   |
|  Jun 96   Joel Gales    Original Programmer                                 |
|                                                                             |
|  END_PROLOG                                                                 |
-----------------------------------------------------------------------------*/
int32
SWinqgeofields(int32 swathID, char *fieldlist, int32 rank[],
	       int32 numbertype[])
{

    int32           nflds;	/* Number of Geolocation fields */

    /* Call "SWinqfields" routine */
    /* -------------------------- */
    nflds = SWinqfields(swathID, "Geolocation Fields", fieldlist, rank,
			numbertype);

    return (nflds);

}




/*----------------------------------------------------------------------------|
|  BEGIN_PROLOG                                                               |
|                                                                             |
|  FUNCTION: SWinqdatafields                                                  |
|                                                                             |
|  DESCRIPTION: Inquires about data fields in swath                           |
|                                                                             |
|                                                                             |
|  Return Value    Type     Units     Description                             |
|  ============   ======  =========   =====================================   |
|  nflds          int32               Number of data fields in swath          |
|                                                                             |
|  INPUTS:                                                                    |
|  swathID        int32               swath structure ID                      |
|                                                                             |
|  OUTPUTS:                                                                   |
|  fieldlist      char                Field names (comma-separated)           |
|  rank           int32               Array of ranks                          |
|  numbertype     int32               Array of HDF number types               |
|                                                                             |
|  NOTES:                                                                     |
|                                                                             |
|                                                                             |
|   Date     Programmer   Description                                         |
|  ======   ============  =================================================   |
|  Jun 96   Joel Gales    Original Programmer                                 |
|                                                                             |
|  END_PROLOG                                                                 |
-----------------------------------------------------------------------------*/
int32
SWinqdatafields(int32 swathID, char *fieldlist, int32 rank[],
		int32 numbertype[])
{

    int32           nflds;	/* Number of Data fields */

    /* Call "SWinqfields" routine */
    /* -------------------------- */
    nflds = SWinqfields(swathID, "Data Fields", fieldlist, rank,
			numbertype);

    return (nflds);

}




/*----------------------------------------------------------------------------|
|  BEGIN_PROLOG                                                               |
|                                                                             |
|  FUNCTION: SWnentries                                                       |
|                                                                             |
|  DESCRIPTION: Returns number of entries and string buffer size              |
|                                                                             |
|                                                                             |
|  Return Value    Type     Units     Description                             |
|  ============   ======  =========   =====================================   |
|  nEntries       int32               Number of entries                       |
|                                                                             |
|  INPUTS:                                                                    |
|  swathID        int32               swath structure ID                      |
|  entrycode      int32               Entry code                              |
|	                              HDFE_NENTDIM  (0)                       |
|	                              HDFE_NENTMAP  (1)                       |
|	                              HDFE_NENTIMAP (2)                       |
|	                              HDFE_NENTGFLD (3)                       |
|	                              HDFE_NENTDFLD (4)                       |
|                                                                             |
|                                                                             |
|  OUTPUTS:                                                                   |
|  strbufsize     int32               Length of comma-separated list          |
|                                     (Does not include null-terminator       |
|                                                                             |
|  NOTES:                                                                     |
|                                                                             |
|                                                                             |
|   Date     Programmer   Description                                         |
|  ======   ============  =================================================   |
|  Jun 96   Joel Gales    Original Programmer                                 |
|  Aug 96   Joel Gales    Make metadata ODL compliant                         |
|  Feb 97   Joel Gales    Set nEntries to -1 if status = -1                   |
|                                                                             |
|  END_PROLOG                                                                 |
-----------------------------------------------------------------------------*/
int32
SWnentries(int32 swathID, int32 entrycode, int32 * strbufsize)

{
    intn            status;	    /* routine return status variable */
    intn            i;		    /* Loop index */

    int32           fid;	    /* HDF-EOS file ID */
    int32           sdInterfaceID;  /* HDF SDS interface ID */
    int32           swVgrpID;	    /* Swath root Vgroup ID */
    int32           idOffset = SWIDOFFSET;	/* Swath ID offset */
    int32           nEntries = 0;   /* Number of entries */
    int32           metaflag;	    /* Old (0), New (1) metadata flag) */
    int32           nVal = 0;	    /* Number of strings to search for */

    char           *metabuf = NULL; /* Pointer to structural metadata (SM) */
    char           *metaptrs[2];    /* Pointers to begin and end of SM section */
    char            swathname[80];  /* Swath Name */
    char           *utlstr;	    /* Utility string */
    char            valName[2][32]; /* Strings to search for */

    /* Allocate space for utility string */
    /* --------------------------------- */
    utlstr = (char *) calloc(UTLSTR_MAX_SIZE, sizeof(char));
    if(utlstr == NULL)
    { 
	HEpush(DFE_NOSPACE,"SWnemtries", __FILE__, __LINE__);
	return(-1);
    }
    /* Check for valid swath id */
    /* ------------------------ */
    status = SWchkswid(swathID, "SWnentries", &fid, &sdInterfaceID, &swVgrpID);

    if (status == 0)
    {
	/* Get swath name */
	Vgetname(SWXSwath[swathID % idOffset].IDTable, swathname);

	/* Zero out string buffer size */
	*strbufsize = 0;


	/*
	 * Get pointer to relevant section within SM and Get names of
	 * metadata strings to inquire about
	 */
	switch (entrycode)
	{
	case HDFE_NENTDIM:
	    /* Dimensions */
	    {
		metabuf = (char *) EHmetagroup(sdInterfaceID, swathname, "s",
					       "Dimension", metaptrs);
		if(metabuf == NULL)
		{
		    free(utlstr);
		    return(-1);
		}
		nVal = 1;
		strcpy(&valName[0][0], "DimensionName");
	    }
	    break;

	case HDFE_NENTMAP:
	    /* Dimension Maps */
	    {
		metabuf = (char *) EHmetagroup(sdInterfaceID, swathname, "s",
					       "DimensionMap", metaptrs);
		if(metabuf == NULL)
		{
		    free(utlstr);
		    return(-1);
		}
		nVal = 2;
		strcpy(&valName[0][0], "GeoDimension");
		strcpy(&valName[1][0], "DataDimension");
	    }
	    break;

	case HDFE_NENTIMAP:
	    /* Indexed Dimension Maps */
	    {
		metabuf = (char *) EHmetagroup(sdInterfaceID, swathname, "s",
					     "IndexDimensionMap", metaptrs);
		if(metabuf == NULL)
		{
		    free(utlstr);
		    return(-1);
		}
		nVal = 2;
		strcpy(&valName[0][0], "GeoDimension");
		strcpy(&valName[1][0], "DataDimension");
	    }
	    break;

	case HDFE_NENTGFLD:
	    /* Geolocation Fields */
	    {
		metabuf = (char *) EHmetagroup(sdInterfaceID, swathname, "s",
					       "GeoField", metaptrs);
		if(metabuf == NULL)
		{
		    free(utlstr);
		    return(-1);
		}
		nVal = 1;
		strcpy(&valName[0][0], "GeoFieldName");
	    }
	    break;

	case HDFE_NENTDFLD:
	    /* Data Fields */
	    {
		metabuf = (char *) EHmetagroup(sdInterfaceID, swathname, "s",
					       "DataField", metaptrs);
		if(metabuf == NULL)
		{
		    free(utlstr);
		    return(-1);
		}
		nVal = 1;
		strcpy(&valName[0][0], "DataFieldName");
	    }
	    break;
	}


	/*
	 * Check for presence of 'GROUP="' string If found then old metadata,
	 * search on OBJECT string
	 */
        if (metabuf)
        {
            metaflag = (strstr(metabuf, "GROUP=\"") == NULL) ? 1 : 0;
            if (metaflag == 0)
            {
                nVal = 1;
                strcpy(&valName[0][0], "\t\tOBJECT");
            }


            /* Begin loop through entries in metadata */
            /* -------------------------------------- */
            while (1)
            {
                /* Search for first string */
                strcpy(utlstr, &valName[0][0]);
                strcat(utlstr, "=");
                metaptrs[0] = strstr(metaptrs[0], utlstr);

                /* If found within relevant metadata section ... */
                if (metaptrs[0] < metaptrs[1] && metaptrs[0] != NULL)
                {
                    for (i = 0; i < nVal; i++)
                    {
                        /*
                         * Get all string values Don't count quotes
                         */
                        EHgetmetavalue(metaptrs, &valName[i][0], utlstr);
                        *strbufsize += (int32)strlen(utlstr) - 2;
                    }
                    /* Increment number of entries */
                    nEntries++;

                    /* Go to end of OBJECT */
                    metaptrs[0] = strstr(metaptrs[0], "END_OBJECT");
                }
                else
                    /* No more entries found */
                {
                    break;
                }
            }
            free(metabuf);
        }


	/* Count comma separators & slashes (if mappings) */
	/* ---------------------------------------------- */
	if (nEntries > 0)
	{
	    *strbufsize += nEntries - 1;
	    *strbufsize += (nVal - 1) * nEntries;
	}
    }


    /* Set nEntries to -1 if error status exists */
    /* ----------------------------------------- */
    if (status == -1)
	nEntries = -1;

    free(utlstr);

    return (nEntries);
}





/*----------------------------------------------------------------------------|
|  BEGIN_PROLOG                                                               |
|                                                                             |
|  FUNCTION: SWinqswath                                                       |
|                                                                             |
|  DESCRIPTION: Returns number and names of swath structures in file          |
|                                                                             |
|                                                                             |
|  Return Value    Type     Units     Description                             |
|  ============   ======  =========   =====================================   |
|  nSwath         int32               Number of swath structures in file      |
|                                                                             |
|  INPUTS:                                                                    |
|  filename       char                HDF-EOS filename                        |
|                                                                             |
|  OUTPUTS:                                                                   |
|  swathlist      char                List of swath names (comma-separated)   |
|  strbufsize     int32               Length of swathlist                     |
|                                                                             |
|  NOTES:                                                                     |
|                                                                             |
|                                                                             |
|   Date     Programmer   Description                                         |
|  ======   ============  =================================================   |
|  Jun 96   Joel Gales    Original Programmer                                 |
|                                                                             |
|  END_PROLOG                                                                 |
-----------------------------------------------------------------------------*/
int32
SWinqswath(const char *filename, char *swathlist, int32 * strbufsize)
{
    int32           nSwath;	/* Number of swath structures in file */

    /* Call "EHinquire" routine */
    /* ------------------------ */
    nSwath = EHinquire(filename, "SWATH", swathlist, strbufsize);

    return (nSwath);
}



/*----------------------------------------------------------------------------|
|  BEGIN_PROLOG                                                               |
|                                                                             |
|  FUNCTION: SW1dfldsrch                                                      |
|                                                                             |
|  DESCRIPTION: Retrieves information about a 1D field                        |
|                                                                             |
|                                                                             |
|  Return Value    Type     Units     Description                             |
|  ============   ======  =========   =====================================   |
|  status         intn                return status (0) SUCCEED, (-1) FAIL    |
|                                                                             |
|  INPUTS:                                                                    |
|  fid            int32               HDF-EOS file ID                         |
|  swathID        int32               swath structure ID                      |
|  fieldname      const char          field name                              |
|  access         const char          Access code (w/r)                       |
|                                                                             |
|                                                                             |
|  OUTPUTS:                                                                   |
|  vgidout        int32               Field (geo/data) vgroup ID              |
|  vdataIDout     int32               Field Vdata ID                          |
|  fldtype        int32               Field type                              |
|                                                                             |
|  NOTES:                                                                     |
|                                                                             |
|                                                                             |
|   Date     Programmer   Description                                         |
|  ======   ============  =================================================   |
|  Jun 96   Joel Gales    Original Programmer                                 |
|                                                                             |
|  END_PROLOG                                                                 |
-----------------------------------------------------------------------------*/
static intn
SW1dfldsrch(int32 fid, int32 swathID, const char *fieldname, const char *i_access,
	    int32 * vgidout, int32 * vdataIDout, int32 * fldtype)

{
    intn            status = 0;	/* routine return status variable */

    int32           sID;	/* SwathID - offset */
    int32           vgid;	/* Swath Geo or Data Vgroup ID */
    int32           vdataID;	/* 1d field vdata */
    int32           idOffset = SWIDOFFSET;	/* Swath ID offset */


    /* Compute "reduced" swath ID */
    /* -------------------------- */
    sID = swathID % idOffset;


    /* Get Geolocation Vgroup id and 1D field name Vdata id */
    /* ---------------------------------------------------- */
    vgid = SWXSwath[sID].VIDTable[0];
    vdataID = EHgetid(fid, vgid, fieldname, 1, i_access);
    *fldtype = 0;


    /*
     * If name not found in Geolocation Vgroup then detach Geolocation Vgroup
     * and search in Data Vgroup
     */
    if (vdataID == -1)
    {
	vgid = SWXSwath[sID].VIDTable[1];;
	vdataID = EHgetid(fid, vgid, fieldname, 1, i_access);
	*fldtype = 1;

	/* If field also not found in Data Vgroup then set error status */
	/* ------------------------------------------------------------ */
	if (vdataID == -1)
	{
	    status = -1;
	    vgid = -1;
	    vdataID = -1;
	}
    }
    *vgidout = vgid;
    *vdataIDout = vdataID;

    return (status);
}





/*----------------------------------------------------------------------------|
|  BEGIN_PROLOG                                                               |
|                                                                             |
|  FUNCTION: SWSDfldsrch                                                      |
|                                                                             |
|  DESCRIPTION: Retrieves information SDS field                               |
|                                                                             |
|                                                                             |
|  Return Value    Type     Units     Description                             |
|  ============   ======  =========   =====================================   |
|  status         intn                return status (0) SUCCEED, (-1) FAIL    |
|                                                                             |
|  INPUTS:                                                                    |
|  swathID        int32               swath structure ID                      |
|  sdInterfaceID  int32               SD interface ID                         |
|  fieldname      const char          field name                              |
|                                                                             |
|                                                                             |
|  OUTPUTS:                                                                   |
|  sdid           int32               SD element ID                           |
|  rankSDS        int32               Rank of SDS                             |
|  rankFld        int32               True rank of field (merging)            |
|  offset         int32               Offset of field within merged field     |
|  dims           int32               Dimensions of field                     |
|  solo           int32               Solo field flag                         |
|                                                                             |
|  NOTES:                                                                     |
|                                                                             |
|                                                                             |
|   Date     Programmer   Description                                         |
|  ======   ============  =================================================   |
|  Jun 96   Joel Gales    Original Programmer                                 |
|  Aug 96   Joel Gales    Make metadata ODL compliant                         |
|                                                                             |
|  END_PROLOG                                                                 |
-----------------------------------------------------------------------------*/
static intn
SWSDfldsrch(int32 swathID, int32 sdInterfaceID, const char *fieldname,
            int32 * sdid, int32 * rankSDS, int32 * rankFld, int32 * offset,
            int32 dims[], int32 * solo)
{
    intn            i;		/* Loop index */
    intn            status = -1;/* routine return status variable */

    int32           sID;	/* SwathID - offset */
    int32           idOffset = SWIDOFFSET;	/* Swath ID offset */
    int32           dum;	/* Dummy variable */
    int32           dums[128];	/* Dummy array */
    int32           attrIndex;	/* Attribute l_index */

    char            name[2048];	/* Merged-Field Names */
    char            swathname[80];	/* Swath Name */
    char           *utlstr;	/* Utility string */
    char           *metabuf;	/* Pointer to structural metadata (SM) */
    char           *metaptrs[2];/* Pointers to begin and end of SM section */
    char           *oldmetaptr;	/* Pointer within SM section */


    /* Allocate space for utility string */
    /* --------------------------------- */
    utlstr = (char *) calloc(UTLSTR_MAX_SIZE, sizeof(char));
    if(utlstr == NULL)
    { 
	HEpush(DFE_NOSPACE,"SWSDfldsrch", __FILE__, __LINE__);
	return(-1);
    }
    /* Set solo flag to 0 (no) */
    /* ----------------------- */
    *solo = 0;


    /* Compute "reduced" swath ID */
    /* -------------------------- */
    sID = swathID % idOffset;


    /* Loop through all SDSs in swath */
    /* ------------------------------ */
    for (i = 0; i < SWXSwath[sID].nSDS; i++)
    {
	/* If active SDS ... */
	/* ----------------- */
	if (SWXSwath[sID].sdsID[i] != 0)
	{
	    /* Get SDS ID, name, rankSDS, and dimensions */
	    /* ----------------------------------------- */
	    *sdid = SWXSwath[sID].sdsID[i];
	    SDgetinfo(*sdid, name, rankSDS, dims, &dum, &dum);
	    *rankFld = *rankSDS;

	    /* If merged field ... */
	    /* ------------------- */
	    if (strstr(name, "MRGFLD_") == &name[0])
	    {
		/* Get swath name */
		/* -------------- */
		Vgetname(SWXSwath[sID].IDTable, swathname);


		/* Get pointers to "MergedFields" section within SM */
		/* ------------------------------------------------ */
		metabuf = (char *) EHmetagroup(sdInterfaceID, swathname, "s",
					       "MergedFields", metaptrs);
		if(metabuf == NULL)
		{
		    free(utlstr);
		    return(-1);
		}

		/* Store metaptr in order to recover */
		/* --------------------------------- */
		oldmetaptr = metaptrs[0];


		/* Search for Merged field name */
		/* ---------------------------- */
		snprintf(utlstr, UTLSTR_MAX_SIZE, "%s%.480s%s", "MergedFieldName=\"",
			name, "\"\n");
		metaptrs[0] = strstr(metaptrs[0], utlstr);


		/* If not found check for old metadata */
		/* ----------------------------------- */
		if (metaptrs[0] == NULL)
		{
		    snprintf(utlstr, UTLSTR_MAX_SIZE, "%s%.480s%s", "OBJECT=\"", name, "\"\n");
		    metaptrs[0] = strstr(oldmetaptr, utlstr);
		}


		/* Get field list and strip off leading and trailing quotes */
		EHgetmetavalue(metaptrs, "FieldList", name);  /* not return status --xhua */
		memmove(name, name + 1, strlen(name) - 2);
		name[strlen(name) - 2] = 0;

		/* Search for desired field within merged field list */
		snprintf(utlstr, UTLSTR_MAX_SIZE, "%s%s%s", "\"", fieldname, "\"");
		dum = EHstrwithin(utlstr, name, ',');

		free(metabuf);
	    }
	    else
	    {
		/* If solo (unmerged) check if SDS name matches fieldname */
		/* ------------------------------------------------------ */
		dum = EHstrwithin(fieldname, name, ',');
		if (dum != -1)
		{
		    *solo = 1;
		    *offset = 0;
		}
	    }


	    /* If field found ... */
	    /* ------------------ */
	    if (dum != -1)
	    {
		status = 0;

		/* If merged field ... */
		/* ------------------- */
		if (*solo == 0)
		{
		    /* Get "Field Offsets" SDS attribute l_index */
		    /* --------------------------------------- */
		    attrIndex = SDfindattr(*sdid, "Field Offsets");

		    /*
		     * If attribute exists then get offset of desired field
		     * within merged field
		     */
		    if (attrIndex != -1)
		    {
			SDreadattr(*sdid, attrIndex, (VOIDP) dums);
			*offset = dums[dum];
		    }


		    /* Get "Field Dims" SDS attribute l_index */
		    /* ------------------------------------ */
		    attrIndex = SDfindattr(*sdid, "Field Dims");

		    /*
		     * If attribute exists then get 0th dimension of desired
		     * field within merged field
		     */
		    if (attrIndex != -1)
		    {
			SDreadattr(*sdid, attrIndex, (VOIDP) dums);
			dims[0] = dums[dum];

			/* If this dimension = 1 then field is really 2 dim */
			/* ------------------------------------------------ */
			if (dums[dum] == 1)
			{
			    *rankFld = 2;
			}
		    }
		}


		/* Break out of SDS loop */
		/* --------------------- */
		break;
	    }			/* End of found field section */
	}
	else
	{
	    /* First non-active SDS signifies no more, break out of SDS loop */
	    /* ------------------------------------------------------------- */
	    break;
	}
    }

    free(utlstr);

    return (status);
}





/*----------------------------------------------------------------------------|
|  BEGIN_PROLOG                                                               |
|                                                                             |
|  FUNCTION: SWwrrdfield                                                      |
|                                                                             |
|  DESCRIPTION: Writes/Reads fields                                           |
|                                                                             |
|                                                                             |
|  Return Value    Type     Units     Description                             |
|  ============   ======  =========   =====================================   |
|  status         intn                return status (0) SUCCEED, (-1) FAIL    |
|                                                                             |
|  INPUTS:                                                                    |
|  swathID        int32               swath structure ID                      |
|  fieldname      const char          fieldname                               |
|  code           const char          Write/Read code (w/r)                   |
|  start          int32               start array                             |
|  stride         int32               stride array                            |
|  edge           int32               edge array                              |
|  datbuf         void                data buffer for read                    |
|                                                                             |
|                                                                             |
|  OUTPUTS:                                                                   |
|  datbuf         void                data buffer for write                   |
|                                                                             |
|  NOTES:                                                                     |
|                                                                             |
|                                                                             |
|   Date     Programmer   Description                                         |
|  ======   ============  =================================================   |
|  Jun 96   Joel Gales    Original Programmer                                 |
|  Feb 97   Joel Gales    Stride = 1 HDF compression workaround               |
|                                                                             |
|  END_PROLOG                                                                 |
-----------------------------------------------------------------------------*/
static intn
SWwrrdfield(int32 swathID, const char *fieldname, const char *code,
	    int32 start[], int32 stride[], int32 edge[], VOIDP datbuf)

{
    intn            i;		/* Loop index */
    intn            status = 0;	/* routine return status variable */

    int32           fid;	/* HDF-EOS file ID */
    int32           sdInterfaceID;	/* HDF SDS interface ID */
    int32           vgid;	/* Swath Geo or Data Vgroup ID */
    int32           sdid;	/* SDS ID */
    int32           dum;	/* Dummy variable */
    int32           rankSDS;	/* Rank of SDS */
    int32           rankFld;	/* Rank of field */

    int32           vdataID;	/* 1d field vdata */
    int32           recsize;	/* Vdata record size */
    int32           fldsize;	/* Field size */
    int32           nrec;	/* Number of records in Vdata */

    int32           offset[8];	/* I/O offset (start) */
    int32           incr[8];	/* I/O increment (stride) */
    int32           count[8];	/* I/O count (edge) */
    int32           dims[8];	/* Field/SDS dimensions */
    int32           mrgOffset;	/* Merged field offset */
    int32           nflds;	/* Number of fields in Vdata */
    int32           strideOne;	/* Strides = 1 flag */

    uint8          *buf;	/* I/O (transfer) buffer */
    uint8          *fillbuf;	/* Fill value buffer */

    char            attrName[80];	/* Name of fill value attribute */
    char           *ptr[64];	/* String pointer array */
    char            fieldlist[256];	/* Vdata field list */


    /* Check for valid swath ID */
    /* ------------------------ */
    status = SWchkswid(swathID, "SWwrrdfield", &fid, &sdInterfaceID, &dum);


    if (status == 0)
    {

	/* Check whether fieldname is in SDS (multi-dim field) */
	/* --------------------------------------------------- */
	status = SWSDfldsrch(swathID, sdInterfaceID, fieldname, &sdid,
			     &rankSDS, &rankFld, &mrgOffset, dims, &dum);

	/* Multi-Dimensional Field Section */
	/* ------------------------------- */
	if (status != -1)
	{
	    /* Set I/O offset Section */
	    /* ---------------------- */

	    /*
	     * If start == NULL (default) set I/O offset of 0th field to
	     * offset within merged field (if any) and the rest to 0
	     */
	    if (start == NULL)
	    {
		for (i = 0; i < rankSDS; i++)
		{
		    offset[i] = 0;
		}
		offset[0] = mrgOffset;
	    }
	    else
	    {
		/*
		 * ... otherwise set I/O offset to user values, adjusting the
		 * 0th field with the merged field offset (if any)
		 */
		if (rankFld == rankSDS)
		{
		    for (i = 0; i < rankSDS; i++)
		    {
			offset[i] = start[i];
		    }
		    offset[0] += mrgOffset;
		}
		else
		{
		    /*
		     * If field really 2-dim merged in 3-dim field then set
		     * 0th field offset to merge offset and then next two to
		     * the user values
		     */
		    for (i = 0; i < rankFld; i++)
		    {
			offset[i + 1] = start[i];
		    }
		    offset[0] = mrgOffset;
		}
	    }



	    /* Set I/O stride Section */
	    /* ---------------------- */

	    /*
	     * If stride == NULL (default) set I/O stride to 1
	     */
	    if (stride == NULL)
	    {
		for (i = 0; i < rankSDS; i++)
		{
		    incr[i] = 1;
		}
	    }
	    else
	    {
		/*
		 * ... otherwise set I/O stride to user values
		 */
		if (rankFld == rankSDS)
		{
		    for (i = 0; i < rankSDS; i++)
		    {
			incr[i] = stride[i];
		    }
		}
		else
		{
		    /*
		     * If field really 2-dim merged in 3-dim field then set
		     * 0th field stride to 1 and then next two to the user
		     * values.
		     */
		    for (i = 0; i < rankFld; i++)
		    {
			incr[i + 1] = stride[i];
		    }
		    incr[0] = 1;
		}
	    }



	    /* Set I/O count Section */
	    /* --------------------- */

	    /*
	     * If edge == NULL (default) set I/O count to number of remaining
	     * entries (dims - start) / increment.  Note that 0th field
	     * offset corrected for merged field offset (if any).
	     */
	    if (edge == NULL)
	    {
		for (i = 1; i < rankSDS; i++)
		{
		    count[i] = (dims[i] - offset[i]) / incr[i];
		}
		count[0] = (dims[0] - (offset[0] - mrgOffset)) / incr[0];
	    }
	    else
	    {
		/*
		 * ... otherwise set I/O count to user values
		 */
		if (rankFld == rankSDS)
		{
		    for (i = 0; i < rankSDS; i++)
		    {
			count[i] = edge[i];
		    }
		}
		else
		{
		    /*
		     * If field really 2-dim merged in 3-dim field then set
		     * 0th field count to 1 and then next two to the user
		     * values.
		     */
		    for (i = 0; i < rankFld; i++)
		    {
			count[i + 1] = edge[i];
		    }
		    count[0] = 1;
		}
	    }

	    /* Perform I/O with relevant HDF I/O routine */
	    /* ----------------------------------------- */
	    if (strcmp(code, "w") == 0)
	    {
		/* Set strideOne to true (1) */
		/* ------------------------- */
		strideOne = 1;


		/* If incr[i] != 1 set strideOne to false (0) */
		/* ------------------------------------------ */
		for (i = 0; i < rankSDS; i++)
		{
		    if (incr[i] != 1)
		    {
			strideOne = 0;
			break;
		    }
		}


		/*
		 * If strideOne is true use NULL parameter for stride. This
		 * is a work-around to HDF compression problem
		 */
		if (strideOne == 1)
		{
		    status = SDwritedata(sdid, offset, NULL, count,
					 (VOIDP) datbuf);
		}
		else
		{
		    status = SDwritedata(sdid, offset, incr, count,
					 (VOIDP) datbuf);
		}
	    }
	    else
	    {
		status = SDreaddata(sdid, offset, incr, count,
				    (VOIDP) datbuf);
	    }
	}			/* End of Multi-Dimensional Field Section */
	else
	{

	    /* One-Dimensional Field Section */
	    /* ----------------------------- */

	    /* Check fieldname within 1d field Vgroups */
	    /* --------------------------------------- */
	    status = SW1dfldsrch(fid, swathID, fieldname, code,
				 &vgid, &vdataID, &dum);

	    if (status != -1)
	    {

		/* Get number of records */
		/* --------------------- */
		nrec = VSelts(vdataID);


		/* Set offset, increment, & count */
		/* ------------------------------ */
		offset[0] = (start == NULL) ? 0 : start[0];
		incr[0] = (stride == NULL) ? 1 : stride[0];
		count[0] = (edge == NULL)
		    ? (nrec - offset[0]) / incr[0]
		    : edge[0];



		/* Write Section */
		/* ------------- */
		if (strcmp(code, "w") == 0)
		{
		    /* Get size of field and setup fill buffer */
		    /* --------------------------------------- */
		    fldsize = VSsizeof(vdataID, (char *)fieldname);
		    fillbuf = (uint8 *) calloc(fldsize, 1);
		    if(fillbuf == NULL)
		    { 
			HEpush(DFE_NOSPACE,"SWwrrdfield", __FILE__, __LINE__);
			return(-1);
		    }

		    /* Get size of record in Vdata and setup I/O buffer */
		    /* ------------------------------------------------ */
		    VSQueryvsize(vdataID, &recsize);
		    buf = (uint8 *) calloc(recsize, count[0] * incr[0]);
		    if(buf == NULL)
		    { 
			HEpush(DFE_NOSPACE,"SWwrrdfield", __FILE__, __LINE__);
			return(-1);
		    }


		    /* Get names and number of fields in each record  */
		    /* ---------------------------------------------- */
		    VSgetfields(vdataID, fieldlist);
		    dum = EHstrwithin(fieldname, fieldlist, ',');
		    nflds = EHparsestr(fieldlist, ',', ptr, NULL);


		    /* Get Merged Field Offset (if any) */
		    /* -------------------------------- */
		    if (nflds > 1)
		    {
			if (dum > 0)
			{
			    *(ptr[dum] - 1) = 0;
			    mrgOffset = VSsizeof(vdataID, fieldlist);
			    *(ptr[dum] - 1) = ',';
			}
			else
			{
			    mrgOffset = 0;
			}

			/* Read records to recover previously written data */
			/* status = */ VSsetfields(vdataID, fieldlist);
			/* status = */ VSseek(vdataID, offset[0]);
			nrec = VSread(vdataID, buf, count[0] * incr[0],
				      FULL_INTERLACE);
		    }
		    else
		    {
			mrgOffset = 0;
		    }



		    /* Fill buffer with "Fill" value (if any) */
		    /* -------------------------------------- */
                    snprintf( attrName, sizeof(attrName), "_FV_%s", fieldname);

		    status = SWreadattr(swathID, attrName, (char *) fillbuf);
		    if (status == 0)
		    {
			for (i = 0; i < count[0] * incr[0]; i++)
			{
			    memcpy(buf + i * recsize + mrgOffset,
				   fillbuf, fldsize);
			}
		    }


		    /* Write new data into buffer */
		    /* -------------------------- */
		    if (incr[0] == 1 && nflds == 1)
		    {
			memcpy(buf, datbuf, count[0] * recsize);
		    }
		    else
		    {
			for (i = 0; i < count[0]; i++)
			{
			    memcpy(buf + i * recsize * incr[0] + mrgOffset,
				   (uint8 *) datbuf + i * fldsize, fldsize);
			}
		    }


		    /* If append read last record */
		    /* -------------------------- */
		    if (offset[0] == nrec)
		    {
			/* abe added "status =" to next line 8/8/97 */
			status = VSseek(vdataID, offset[0] - 1);
			VSread(vdataID, fillbuf, 1, FULL_INTERLACE);
		    }
		    else
		    {
			status = VSseek(vdataID, offset[0]);
		    }


		    /* Write data into Vdata */
		    /* --------------------- */
		    nrec = VSwrite(vdataID, buf, count[0] * incr[0],
				   FULL_INTERLACE);

		    free(fillbuf);
                    if (status > 0)
                       status = 0;

		}		/* End Write Section */
		else
		{
		    /* Read Section */
		    /* ------------ */
		    status = VSsetfields(vdataID, fieldname);
		    fldsize = VSsizeof(vdataID, (char *)fieldname);
		    buf = (uint8 *) calloc(fldsize, count[0] * incr[0]);
		    if(buf == NULL)
		    { 
			HEpush(DFE_NOSPACE,"SWwrrdfield", __FILE__, __LINE__);
			return(-1);
		    }

		    (void) VSseek(vdataID, offset[0]);
		    (void) VSread(vdataID, buf, count[0] * incr[0],
			   FULL_INTERLACE);


		    /* Copy from input buffer to returned data buffer */
		    /* ---------------------------------------------- */
		    if (incr[0] == 1)
		    {
			memcpy(datbuf, buf, count[0] * fldsize);
		    }
		    else
		    {
			for (i = 0; i < count[0]; i++)
			{
			    memcpy((uint8 *) datbuf + i * fldsize,
				   buf + i * fldsize * incr[0], fldsize);
			}
		    }

		}		/* End Read Section */

		free(buf);
		VSdetach(vdataID);
	    }
	    else
	    {
		HEpush(DFE_GENAPP, "SWwrrdfield", __FILE__, __LINE__);
		HEreport("Fieldname \"%s\" does not exist.\n", fieldname);
	    }
	}			/* End One-D Field Section */

    }
    return (status);
}



/*----------------------------------------------------------------------------|
|  BEGIN_PROLOG                                                               |
|                                                                             |
|  FUNCTION: SWwritefield                                                     |
|                                                                             |
|  DESCRIPTION: Writes data to field                                          |
|                                                                             |
|                                                                             |
|  Return Value    Type     Units     Description                             |
|  ============   ======  =========   =====================================   |
|  status         intn                return status (0) SUCCEED, (-1) FAIL    |
|                                                                             |
|  INPUTS:                                                                    |
|  swathID        int32               swath structure ID                      |
|  fieldname      char                fieldname                               |
|  start          int32               start array                             |
|  stride         int32               stride array                            |
|  edge           int32               edge array                              |
|                                                                             |
|                                                                             |
|  OUTPUTS:                                                                   |
|  data           void                data buffer for write                   |
|                                                                             |
|  NOTES:                                                                     |
|                                                                             |
|                                                                             |
|   Date     Programmer   Description                                         |
|  ======   ============  =================================================   |
|  Jun 96   Joel Gales    Original Programmer                                 |
|                                                                             |
|  END_PROLOG                                                                 |
-----------------------------------------------------------------------------*/
intn
SWwritefield(int32 swathID, const char *fieldname,
	     int32 start[], int32 stride[], int32 edge[], VOIDP data)

{
    intn            status = 0;	/* routine return status variable */

    status = SWwrrdfield(swathID, fieldname, "w", start, stride, edge,
			 data);
    return (status);
}






/*----------------------------------------------------------------------------|
|  BEGIN_PROLOG                                                               |
|                                                                             |
|  FUNCTION: SWreadfield                                                      |
|                                                                             |
|  DESCRIPTION: Reads data from field                                         |
|                                                                             |
|  Return Value    Type     Units     Description                             |
|  ============   ======  =========   =====================================   |
|  status         intn                return status (0) SUCCEED, (-1) FAIL    |
|                                                                             |
|  INPUTS:                                                                    |
|  swathID        int32               swath structure ID                      |
|  fieldname      const char          fieldname                               |
|  start          int32               start array                             |
|  stride         int32               stride array                            |
|  edge           int32               edge array                              |
|  buffer         void                data buffer for read                    |
|                                                                             |
|                                                                             |
|  OUTPUTS:                                                                   |
|     None                                                                    |
|                                                                             |
|  NOTES:                                                                     |
|                                                                             |
|                                                                             |
|   Date     Programmer   Description                                         |
|  ======   ============  =================================================   |
|  Jun 96   Joel Gales    Original Programmer                                 |
|                                                                             |
|  END_PROLOG                                                                 |
-----------------------------------------------------------------------------*/
intn
SWreadfield(int32 swathID, const char *fieldname,
	    int32 start[], int32 stride[], int32 edge[], VOIDP buffer)

{
    intn            status = 0;	/* routine return status variable */

    status = SWwrrdfield(swathID, fieldname, "r", start, stride, edge,
			 buffer);
    return (status);
}




/*----------------------------------------------------------------------------|
|  BEGIN_PROLOG                                                               |
|                                                                             |
|  FUNCTION: SWdefboxregion                                                   |
|                                                                             |
|  DESCRIPTION: Finds swath cross tracks within area of interest and returns  |
|               region ID                                                     |
|                                                                             |
|                                                                             |
|  Return Value    Type     Units     Description                             |
|  ============   ======  =========   =====================================   |
|  regionID       int32               Region ID                               |
|                                                                             |
|  INPUTS:                                                                    |
|  swathID        int32               Swath structure ID                      |
|  cornerlon      float64  dec deg    Longitude of opposite corners of box    |
|  cornerlat      float64  dec deg    Latitude of opposite corners of box     |
|  mode           int32               Search mode                             |
|                                     HDFE_MIDPOINT - Use midpoint of Xtrack  |
|                                     HDFE_ENDPOINT - Use endpoints of Xtrack |
|                                     HDFE_ANYPOINT - Use all points of Xtrack|
|                                                                             |
|  OUTPUTS:                                                                   |
|             None                                                            |
|                                                                             |
|  NOTES:                                                                     |
|                                                                             |
|                                                                             |
|   Date     Programmer   Description                                         |
|  ======   ============  =================================================   |
|  Jun 96   Joel Gales    Original Programmer                                 |
|  Oct 96   Joel Gales    Add ability to handle regions crossing date line    |
|  Dec 96   Joel Gales    Add multiple vertical subsetting capability         |
|  Jul 98   Abe Taaheri   Fixed core dump in SWregioninfo associated with     |
|                         SWXRegion[k]->nRegions exceeding MAXNREGIONS in     |
|                         this function                                       |
|  Aug 99   Abe Taaheri   Fixed the code so that all cross tracks or all      |
|                         points on the along track that fall inside the box  |
|                         are identified. At the same time added code to      |
|                         function "updatescene" to reject cases where there  |
|                         is single cross track in the box (for LANDSAT)      |
|  Jun 03   Abe Taaheri   Added a few lines to report error and return -1 if  |
|                         regionID exceeded NSWATHREGN                        |
|  Mar 04   Abe Taaheri   Added recognition for GeodeticLatitude              |
|                                                                             |
|  END_PROLOG                                                                 |
-----------------------------------------------------------------------------*/
int32
SWdefboxregion(int32 swathID, float64 cornerlon[], float64 cornerlat[],
	       int32 mode)
{
    intn            i;		/* Loop index */
    intn            j = 0;		/* Loop index */
    intn            k;		/* Loop index */
    
    intn            status;	/* routine return status variable */
    intn            statLon;	/* Status from SWfieldinfo for longitude */
    intn            statLat;	/* Status from SWfieldinfo for latitude */
    intn            statCoLat = -1;	/* Status from SWfieldinfo for
					 * Colatitude */
    intn            statGeodeticLat = -1; /* Status from SWfieldinfo for
					 * GeodeticLatitude */

    uint8           found = 0;	/* Found flag */
    uint8          *flag;	/* Pointer to track flag array */
    intn           validReg = -1; /* -1 is invalid validReg */ 
    
    int32           fid;	/* HDF-EOS file ID */
    int32           sdInterfaceID;	/* HDF SDS interface ID */
    int32           swVgrpID;	/* Swath Vgroup ID */
    int32           rank;	/* Rank of geolocation fields */
    int32           nt;		/* Number type of geolocation fields */
    int32           dims[8];	/* Dimensions of geolocation fields */
    int32           nElem;	/* Number of elements to read */
    int32           bndflag;	/* +/-180 longitude boundary flag */
    int32           lonTest;	/* Longitude test flag */
    int32           latTest;	/* Latitude test flag */
    int32           start[2];	/* Start array (read) */
    int32           stride[2] = {1, 1};	/* Stride array (read) */
    int32           edge[2];	/* Edge array (read) */
    int32           regionID = -1;	/* Region ID (return) */
    int32           anyStart[2];/* ANYPOINT start array (read) */
    int32           anyEdge[2];	/* ANYPOINT edge array (read) */

    float32         temp32;	/* Temporary float32 variable */

    float64         lonTestVal;	/* Longitude test value */
    float64         latTestVal;	/* Latitude test value */
    float64         temp64;	/* Temporary float64 variable */

    char           *lonArr;	/* Longitude data array */
    char           *latArr;	/* Latitude data array */
    char            dimlist[256];	/* Dimension list (geolocation
					 * fields) */
    char            latName[17];/* Latitude field name */
    

    /* Check for valid swath ID */
    /* ------------------------ */
    status = SWchkswid(swathID, "SWdefboxregion", &fid, &sdInterfaceID,
		       &swVgrpID);


    /* Inclusion mode must be between 0 and 2 */
    /* -------------------------------------- */
    if (mode < 0 || mode > 2)
    {
	status = -1;
	HEpush(DFE_GENAPP, "SWdefboxregion", __FILE__, __LINE__);
	HEreport("Improper Inclusion Mode: %d.\n", mode);
    }


    if (status == 0)
    {
	/* Get "Longitude" field info */
	/* -------------------------- */
	statLon = SWfieldinfo(swathID, "Longitude", &rank, dims, &nt, dimlist);
	if (statLon != 0)
	{
	    status = -1;
	    HEpush(DFE_GENAPP, "SWdefboxregion", __FILE__, __LINE__);
	    HEreport("\"Longitude\" field not found.\n");
	}

	/* Get "Latitude" field info */
	/* -------------------------- */
	statLat = SWfieldinfo(swathID, "Latitude", &rank, dims, &nt, dimlist);
	if (statLat != 0)
	{
	    /* If not found check for "Colatitude" field info */
	    /* ---------------------------------------------- */
	    statCoLat = SWfieldinfo(swathID, "Colatitude", &rank, dims, &nt,
				    dimlist);
	    if (statCoLat != 0)
	    {
	      /* Check again for Geodeticlatitude */            
	      statGeodeticLat = SWfieldinfo(swathID, 
					    "GeodeticLatitude", &rank, 
					    dims, &nt, dimlist);
	      if (statGeodeticLat != 0)
		{
		  /* Neither "Latitude" nor "Colatitude" nor
		     "GeodeticLatitude" field found */
		  /* ----------------------------------------------- */
		  status = -1;
		  HEpush(DFE_GENAPP, "SWdefboxregion", __FILE__, __LINE__);
		  HEreport(
			   "Neither \"Latitude\" nor \"Colatitude\" nor \"GeodeticLatitude\" fields found.\n");
		}
	      else
		{
		  /* Latitude field is "GeodeticLatitude" */
		  /* ------------------------------ */
		  strcpy(latName, "GeodeticLatitude");
		}
	    }
	    else
	    {
		/* Latitude field is "Colatitude" */
		/* ------------------------------ */
		strcpy(latName, "Colatitude");
	    }
	}
	else
	{
	    /* Latitude field is "Latitude" */
	    /* ---------------------------- */
	    strcpy(latName, "Latitude");
	}


	if (status == 0)
	{
	    /* Search along entire "Track" dimension from beginning to end */
	    /* ----------------------------------------------------------- */
	    start[0] = 0;
	    edge[0] = dims[0];


	    /* If 1D geolocation fields then set mode to MIDPOINT */
	    /* -------------------------------------------------- */
	    if (rank == 1)
	    {
		mode = HDFE_MIDPOINT;
	    }


	    switch (mode)
	    {
		/* If MIDPOINT search single point in middle of "CrossTrack" */
		/* --------------------------------------------------------- */
	    case HDFE_MIDPOINT:

		start[1] = dims[1] / 2;
		edge[1] = 1;

		break;

		/* If ENDPOINT search 2 points at either end of "CrossTrack" */
		/* --------------------------------------------------------- */
	    case HDFE_ENDPOINT:

		start[1] = 0;
		stride[1] = dims[1] - 1;
		edge[1] = 2;

		break;

		/* If ANYPOINT do initial MIDPOINT search */
		/* -------------------------------------- */
	    case HDFE_ANYPOINT:

		start[1] = dims[1] / 2;
		edge[1] = 1;

		break;
	    }


	    /* Compute number of elements */
	    /* -------------------------- */
	    nElem = edge[0] * edge[1];


	    /* Allocate space for longitude and latitude (float64) */
	    /* --------------------------------------------------- */
	    lonArr = (char *) calloc(nElem, sizeof(float64));
	    if(lonArr == NULL)
	    { 
		HEpush(DFE_NOSPACE,"SWdefboxregion", __FILE__, __LINE__);
		return(-1);
	    }

	    latArr = (char *) calloc(nElem, sizeof(float64));
	    if(latArr == NULL)
	    { 
		HEpush(DFE_NOSPACE,"SWdefboxregion", __FILE__, __LINE__);
		free(lonArr);
		return(-1);
	    }


	    /* Allocate space for flag array (uint8) */
	    /* ------------------------------------- */
	    flag = (uint8 *) calloc(edge[0] + 1, 1);
	    if(flag == NULL)
	    { 
		HEpush(DFE_NOSPACE,"SWdefboxregion", __FILE__, __LINE__);
		free(lonArr);
		free(latArr);
		return(-1);
	    }


	    /* Read Longitude and Latitude fields */
	    /* ---------------------------------- */
	    status = SWreadfield(swathID, "Longitude",
				 start, stride, edge, lonArr);
	    status = SWreadfield(swathID, latName,
				 start, stride, edge, latArr);



	    /*
	     * If geolocation fields are FLOAT32 then cast each entry as
	     * FLOAT64
	     */
	    if (nt == DFNT_FLOAT32)
	    {
		for (i = nElem - 1; i >= 0; i--)
		{
		    memcpy(&temp32, lonArr + 4 * i, 4);
		    temp64 = (float64) temp32;
		    memcpy(lonArr + 8 * i, &temp64, 8);

		    memcpy(&temp32, latArr + 4 * i, 4);
		    temp64 = (float64) temp32;
		    memcpy(latArr + 8 * i, &temp64, 8);
		}
	    }   


	    /* Set boundary flag */
	    /* ----------------- */

	    /*
	     * This variable is set to 1 if the region of interest crosses
	     * the +/- 180 longitude boundary
	     */
	    bndflag = (cornerlon[0] < cornerlon[1]) ? 0 : 1;



	    /* Main Search Loop */
	    /* ---------------- */

	    /* For each track ... */
	    /* ------------------ */

	    for (i = 0; i < edge[0]; i++)
	    {   
		/* For each value from Cross Track ... */
		/* ----------------------------------- */
		for (j = 0; j < edge[1]; j++)
		{
		    /* Read in single lon & lat values from data buffers */
		    /* ------------------------------------------------- */
		    memcpy(&lonTestVal, &lonArr[8 * (i * edge[1] + j)], 8);
		    memcpy(&latTestVal, &latArr[8 * (i * edge[1] + j)], 8);


		    /* If longitude value > 180 convert to -180 to 180 range */
		    /* ----------------------------------------------------- */
		    if (lonTestVal > 180)
		    {
			lonTestVal = lonTestVal - 360;
		    }

		    /* If Colatitude value convert to latitude value */
		    /* --------------------------------------------- */
		    if (statCoLat == 0)
		    {
			latTestVal = 90 - latTestVal;
		    }


		    /* Test if lat value is within range */
		    /* --------------------------------- */
		    latTest = (latTestVal >= cornerlat[0] &&
			       latTestVal <= cornerlat[1]);


		    if (bndflag == 1)
		    {
			/*
			 * If boundary flag set test whether longitude value
			 * is outside region and then flip
			 */
			lonTest = (lonTestVal >= cornerlon[1] &&
				   lonTestVal <= cornerlon[0]);
			lonTest = 1 - lonTest;
		    }
		    else
		    {
			lonTest = (lonTestVal >= cornerlon[0] &&
				   lonTestVal <= cornerlon[1]);
		    }


		    /*
		     * If both longitude and latitude are within region set
		     * flag on for this track
		     */
		    if (lonTest + latTest == 2)
		    {
			flag[i] = 1;
			found = 1;
			break;
		    }
		}
	    }



	    /* ANYPOINT search */
	    /* --------------- */
	    if (mode == HDFE_ANYPOINT && rank > 1)
	    {
		free(lonArr);
		free(latArr);

		/* Allocate space for an entire single cross track */
		/* ----------------------------------------------- */
		lonArr = (char *) calloc(dims[1], sizeof(float64));
		if(lonArr == NULL)
		{ 
		    HEpush(DFE_NOSPACE,"SWdefboxregion", __FILE__, __LINE__);
		    return(-1);
		}

		latArr = (char *) calloc(dims[1], sizeof(float64));
		if(latArr == NULL)
		{ 
		    HEpush(DFE_NOSPACE,"SWdefboxregion", __FILE__, __LINE__);
		    free(lonArr);
		    return(-1);
		}


		/* Setup start and edge */
		/* -------------------- */
		anyStart[1] = 0;
		anyEdge[0] = 1;
		anyEdge[1] = dims[1];
	
               
		/* For each track starting from 0 */
		/* ------------------------------ */
		for (i = 0; i < edge[0]; i++)    
		{
               
		    /* If cross track not in region (with MIDPOINT search ... */
		    /* ------------------------------------------------------ */
		    if (flag[i] == 0)
		    {
			/* Setup track start */
			/* ----------------- */
			anyStart[0] = i;


			/* Read in lon and lat values for cross track */
			/* ------------------------------------------ */
			status = SWreadfield(swathID, "Longitude",
					   anyStart, NULL, anyEdge, lonArr);
			status = SWreadfield(swathID, latName,
					   anyStart, NULL, anyEdge, latArr);



			/*
			 * If geolocation fields are FLOAT32 then cast each
			 * entry as FLOAT64
			 */
			if (nt == DFNT_FLOAT32)
			{
			    for (j = dims[1] - 1; j >= 0; j--)
			    {
				memcpy(&temp32, lonArr + 4 * j, 4);
				temp64 = (float64) temp32;
				memcpy(lonArr + 8 * j, &temp64, 8);

				memcpy(&temp32, latArr + 4 * j, 4);
				temp64 = (float64) temp32;
				memcpy(latArr + 8 * j, &temp64, 8);
			    }
			}


			/* For each value from Cross Track ... */
			/* ----------------------------------- */
			for (j = 0; j < dims[1]; j++)
			{
			    /* Read in single lon & lat values from buffers */
			    /* -------------------------------------------- */
			    memcpy(&lonTestVal, &lonArr[8 * j], 8);
			    memcpy(&latTestVal, &latArr[8 * j], 8);


			    /* If lon value > 180 convert to -180 - 180 range */
			    /* ---------------------------------------------- */
			    if (lonTestVal > 180)
			    {
				lonTestVal = lonTestVal - 360;
			    }

			    /* If Colatitude value convert to latitude value */
			    /* --------------------------------------------- */
			    if (statCoLat == 0)
			    {
				latTestVal = 90 - latTestVal;
			    }


			    /* Test if lat value is within range */
			    /* --------------------------------- */
			    latTest = (latTestVal >= cornerlat[0] &&
				       latTestVal <= cornerlat[1]);


			    if (bndflag == 1)
			    {
				/*
				 * If boundary flag set test whether
				 * longitude value is outside region and then
				 * flip
				 */
				lonTest = (lonTestVal >= cornerlon[1] &&
					   lonTestVal <= cornerlon[0]);
				lonTest = 1 - lonTest;
			    }
			    else
			    {
				lonTest = (lonTestVal >= cornerlon[0] &&
					   lonTestVal <= cornerlon[1]);
			    }


			    /*
			     * If both longitude and latitude are within
			     * region set flag on for this track
			     */
			    if (lonTest + latTest == 2)
			    {
				flag[i] = 1;
				found = 1;
				break;
			    }
			}
		    }
		}
            }

	    /* If within region setup Region Structure */
	    /* --------------------------------------- */
	    if (found == 1)
	    {
		/* For all entries in SWXRegion array ... */
		/* -------------------------------------- */
		for (k = 0; k < NSWATHREGN; k++)
		{
		    /* If empty region ... */
		    /* ------------------- */
		    if (SWXRegion[k] == 0)
		    {
			/* Allocate space for region entry */
			/* ------------------------------- */
			SWXRegion[k] = (struct swathRegion *)
			    calloc(1, sizeof(struct swathRegion));
			if(SWXRegion[k] == NULL)
			{ 
			    HEpush(DFE_NOSPACE,"SWdefboxregion", __FILE__, __LINE__);
			    return(-1);
			}

			/* Store file and swath ID */
			/* ----------------------- */
			SWXRegion[k]->fid = fid;
			SWXRegion[k]->swathID = swathID;


			/* Set Start & Stop Vertical arrays to -1 */
			/* -------------------------------------- */
			for (j = 0; j < 8; j++)
			{
			    SWXRegion[k]->StartVertical[j] = -1;
			    SWXRegion[k]->StopVertical[j] = -1;
			    SWXRegion[k]->StartScan[j] = -1;
			    SWXRegion[k]->StopScan[j] = -1;
			}


			/* Set region ID */
			/* ------------- */
			regionID = k;
			break;
		    }
		}
		if (k >= NSWATHREGN)
		  {
		    HEpush(DFE_GENAPP, "SWdefboxregion", __FILE__, __LINE__);
		    HEreport(
			     "regionID exceeded NSWATHREGN.\n");
                    return (-1);
		  }

		/* Find start and stop of regions */
		/* ------------------------------ */

		/* Subtract previous flag value from current one */
		/* --------------------------------------------- */

		/*
		 * Transition points will have flag value (+1) start or
		 * (255 = (uint8) -1) stop of region
		 */
		for (i = edge[0]; i > 0; i--)
		{
		    flag[i] -= flag[i - 1];
		}


		for (i = 0; i <= edge[0]; i++)
		{
		    /* Start of region */
		    /* --------------- */
		    if (flag[i] == 1)
		    {
			/* Increment (multiple) region counter */
			/* ----------------------------------- */
			j = ++SWXRegion[k]->nRegions;
			
			/* if SWXRegion[k]->nRegions greater than MAXNREGIONS */
			/* free allocated memory and return FAIL */
			
			if ((SWXRegion[k]->nRegions) > MAXNREGIONS)
			{
			    HEpush(DFE_GENAPP, "SWdefboxregion", __FILE__, __LINE__);
			    HEreport("SWXRegion[%d]->nRegions exceeds MAXNREGIONS= %d.\n", k, MAXNREGIONS);
			    free(lonArr);
			    free(latArr);
			    free(flag);
			    return(-1);
			}
			
			SWXRegion[k]->StartRegion[j - 1] = i;
		    }
		    
		    /* End of region */
		    /* ------------- */
		    if (flag[i] == 255)
		    {
			SWXRegion[k]->StopRegion[j - 1] = i - 1;
			validReg = 0;
		    }
		}
	    }
	    free(lonArr);
	    free(latArr);
	    free(flag);
	}
    }
    if(validReg==0)
    {
	return (regionID);
    }
    else
    {
	return (-1);
    }
    
}




/*----------------------------------------------------------------------------|
|  BEGIN_PROLOG                                                               |
|                                                                             |
|  FUNCTION: SWregionl_index                                                    |
|                                                                             |
|  DESCRIPTION: Finds swath cross tracks within area of interest and returns  |
|               region l_index and region ID                                    |
|                                                                             |
|                                                                             |
|  Return Value    Type     Units     Description                             |
|  ============   ======  =========   =====================================   |
|  regionID       int32               Region ID                               |
|                                                                             |
|  INPUTS:                                                                    |
|  swathID        int32               Swath structure ID                      |
|  cornerlon      float64  dec deg    Longitude of opposite corners of box    |
|  cornerlat      float64  dec deg    Latitude of opposite corners of box     |
|  mode           int32               Search mode                             |
|                                     HDFE_MIDPOINT - Use midpoint of Xtrack  |
|                                     HDFE_ENDPOINT - Use endpoints of Xtrack |
|                                     HDFE_ANYPOINT - Use all points of Xtrack|
|                                                                             |
|  OUTPUTS:                                                                   |
|  geodim	  char		      geolocation track dimension             |
|  idxrange	  int32		      indices of region for along track dim.  |
|                                                                             |
|  NOTES:                                                                     |
|                                                                             |
|                                                                             |
|   Date     Programmer   Description                                         |
|  ======   ============  =================================================   |
|  Jun 96   Joel Gales    Original Programmer                                 |
|  Oct 96   Joel Gales    Add ability to handle regions crossing date line    |
|  Dec 96   Joel Gales    Add multiple vertical subsetting capability         |
|  Nov 97   Daw           Add multiple vertical subsetting capability         |
|  END_PROLOG                                                                 |
-----------------------------------------------------------------------------*/
int32
SWregionindex(int32 swathID, float64 cornerlon[], float64 cornerlat[],
	       int32 mode, char *geodim, int32 idxrange[])
{
    intn            i;		/* Loop index */
    intn            j;		/* Loop index */
    intn            k;		/* Loop index */

    intn            l=0;	/* Loop index */
    intn            tmpVal = 0;     /* temp value for start region Delyth Jones*/
  /*intn            j1;  */     /* Loop index */
    intn            status;	/* routine return status variable */
    intn	    mapstatus;	/* status for type of mapping */
    intn            statLon;	/* Status from SWfieldinfo for longitude */
    intn            statLat;	/* Status from SWfieldinfo for latitude */
    intn            statCoLat = -1;	/* Status from SWfieldinfo for
					 * Colatitude */
    intn            statGeodeticLat = -1; /* Status from SWfieldinfo for
					 * GeodeticLatitude */

    uint8           found = 0;	/* Found flag */
    uint8          *flag;	/* Pointer to track flag array */
    intn           validReg = -1; /* -1 is invalid validReg */ 
    
    int32           fid;	/* HDF-EOS file ID */
    int32           sdInterfaceID;	/* HDF SDS interface ID */
    int32           swVgrpID;	/* Swath Vgroup ID */
    int32           rank;	/* Rank of geolocation fields */
    int32           nt;		/* Number type of geolocation fields */
    int32           dims[8];	/* Dimensions of geolocation fields */
    int32           nElem;	/* Number of elements to read */
    int32           bndflag;	/* +/-180 longitude boundary flag */
    int32           lonTest;	/* Longitude test flag */
    int32           latTest;	/* Latitude test flag */
    int32           start[2];	/* Start array (read) */
    int32           stride[2] = {1, 1};	/* Stride array (read) */
    int32           edge[2];	/* Edge array (read) */
    int32           regionID = -1;	/* Region ID (return) */
    int32           anyStart[2];/* ANYPOINT start array (read) */
    int32           anyEdge[2];	/* ANYPOINT edge array (read) */

    float32         temp32;	/* Temporary float32 variable */

    float64         lonTestVal;	/* Longitude test value */
    float64         latTestVal;	/* Latitude test value */
    float64         temp64;	/* Temporary float64 variable */

    char           *lonArr;	/* Longitude data array */
    char           *latArr;	/* Latitude data array */
    char            dimlist[256];	/* Dimension list (geolocation
					 * fields) */
    char            latName[17];/* Latitude field name */


    /* Check for valid swath ID */
    /* ------------------------ */
    status = SWchkswid(swathID, "SWregionl_index", &fid, &sdInterfaceID,
		       &swVgrpID);


    /* Inclusion mode must be between 0 and 2 */
    /* -------------------------------------- */
    if (mode < 0 || mode > 2)
    {
	status = -1;
	HEpush(DFE_GENAPP, "SWregionl_index", __FILE__, __LINE__);
	HEreport("Improper Inclusion Mode: %d.\n", mode);
    }


    if (status == 0)
    {
	/* Get "Longitude" field info */
	/* -------------------------- */
	statLon = SWfieldinfo(swathID, "Longitude", &rank, dims, &nt, dimlist);
	if (statLon != 0)
	{
	    status = -1;
	    HEpush(DFE_GENAPP, "SWregionl_index", __FILE__, __LINE__);
	    HEreport("\"Longitude\" field not found.\n");
	}

	/* Get "Latitude" field info */
	/* -------------------------- */
	statLat = SWfieldinfo(swathID, "Latitude", &rank, dims, &nt, dimlist);
	if (statLat != 0)
	{
	    /* If not found check for "Colatitude" field info */
	    /* ---------------------------------------------- */
	    statCoLat = SWfieldinfo(swathID, "Colatitude", &rank, dims, &nt,
				    dimlist);
	    if (statCoLat != 0)
	    {
	      /* Check again for Geodeticlatitude */            
	      statGeodeticLat = SWfieldinfo(swathID, 
					    "GeodeticLatitude", &rank, 
					    dims, &nt, dimlist);
	      if (statGeodeticLat != 0)
	        {
		  /* Neither "Latitude" nor "Colatitude" field found */
		  /* ----------------------------------------------- */
		  status = -1;
		  HEpush(DFE_GENAPP, "SWregionl_index", __FILE__, __LINE__);
		  HEreport(
			   "Neither \"Latitude\" nor \"Colatitude\" fields found.\n");
		}
	      else
		{
		     /* Latitude field is "Colatitude" */
		     /* ------------------------------ */
		     strcpy(latName, "GeodeticLatitude");
		}
	    }
	    else
	    {
		/* Latitude field is "Colatitude" */
		/* ------------------------------ */
		strcpy(latName, "Colatitude");
	    }
	}
	else
	{
	    /* Latitude field is "Latitude" */
	    /* ---------------------------- */
	    strcpy(latName, "Latitude");
	}

        /* This line modifies the dimlist variable so only the along-track */
        /* dimension remains.                                              */
        /* --------------------------------------------------------------- */
        (void) strtok(dimlist,",");
        mapstatus = SWgeomapinfo(swathID,dimlist);
        (void) strcpy(geodim,dimlist);

	if (status == 0)
	{
	    /* Search along entire "Track" dimension from beginning to end */
	    /* ----------------------------------------------------------- */
	    start[0] = 0;
	    edge[0] = dims[0];


	    /* If 1D geolocation fields then set mode to MIDPOINT */
	    /* -------------------------------------------------- */
	    if (rank == 1)
	    {
		mode = HDFE_MIDPOINT;
	    }


	    switch (mode)
	    {
		/* If MIDPOINT search single point in middle of "CrossTrack" */
		/* --------------------------------------------------------- */
	    case HDFE_MIDPOINT:

		start[1] = dims[1] / 2;
		edge[1] = 1;

		break;

		/* If ENDPOINT search 2 points at either end of "CrossTrack" */
		/* --------------------------------------------------------- */
	    case HDFE_ENDPOINT:

		start[1] = 0;
		stride[1] = dims[1] - 1;
		edge[1] = 2;

		break;

		/* If ANYPOINT do initial MIDPOINT search */
		/* -------------------------------------- */
	    case HDFE_ANYPOINT:

		start[1] = dims[1] / 2;
		edge[1] = 1;

		break;
	    }


	    /* Compute number of elements */
	    /* -------------------------- */
	    nElem = edge[0] * edge[1];


	    /* Allocate space for longitude and latitude (float64) */
	    /* --------------------------------------------------- */
	    lonArr = (char *) calloc(nElem, sizeof(float64));
	    if(lonArr == NULL)
	    { 
		HEpush(DFE_NOSPACE,"SWregionl_index", __FILE__, __LINE__);
		return(-1);
	    }
	    
	    latArr = (char *) calloc(nElem, sizeof(float64));
	    if(latArr == NULL)
	    { 
		HEpush(DFE_NOSPACE,"SWregionl_index", __FILE__, __LINE__);
		free(lonArr);
		return(-1);
	    }


	    /* Allocate space for flag array (uint8) */
	    /* ------------------------------------- */
	    flag = (uint8 *) calloc(edge[0] + 1, 1);
	    if(flag == NULL)
	    { 
		HEpush(DFE_NOSPACE,"SWregionl_index", __FILE__, __LINE__);
		free(lonArr);
		free(latArr);
		return(-1);
	    }


	    /* Read Longitude and Latitude fields */
	    /* ---------------------------------- */
	    status = SWreadfield(swathID, "Longitude",
				 start, stride, edge, lonArr);
	    status = SWreadfield(swathID, latName,
				 start, stride, edge, latArr);



	    /*
	     * If geolocation fields are FLOAT32 then cast each entry as
	     * FLOAT64
	     */
	    if (nt == DFNT_FLOAT32)
	    {
		for (i = nElem - 1; i >= 0; i--)
		{
		    memcpy(&temp32, lonArr + 4 * i, 4);
		    temp64 = (float64) temp32;
		    memcpy(lonArr + 8 * i, &temp64, 8);

		    memcpy(&temp32, latArr + 4 * i, 4);
		    temp64 = (float64) temp32;
		    memcpy(latArr + 8 * i, &temp64, 8);
		}
	    }


	    /* Set boundary flag */
	    /* ----------------- */

	    /*
	     * This variable is set to 1 if the region of interest crosses
	     * the +/- 180 longitude boundary
	     */
	    bndflag = (cornerlon[0] < cornerlon[1]) ? 0 : 1;



	    /* Main Search Loop */
	    /* ---------------- */

	    /* For each track ... */
	    /* ------------------ */
	    for (i = 0; i < edge[0]; i++)
	    {
		/* For each value from Cross Track ... */
		/* ----------------------------------- */
		for (j = 0; j < edge[1]; j++)
		{
		    /* Read in single lon & lat values from data buffers */
		    /* ------------------------------------------------- */
		    memcpy(&lonTestVal, &lonArr[8 * (i * edge[1] + j)], 8);
		    memcpy(&latTestVal, &latArr[8 * (i * edge[1] + j)], 8);


		    /* If longitude value > 180 convert to -180 to 180 range */
		    /* ----------------------------------------------------- */
		    if (lonTestVal > 180)
		    {
			lonTestVal = lonTestVal - 360;
		    }

		    /* If Colatitude value convert to latitude value */
		    /* --------------------------------------------- */
		    if (statCoLat == 0)
		    {
			latTestVal = 90 - latTestVal;
		    }


		    /* Test if lat value is within range */
		    /* --------------------------------- */
		    latTest = (latTestVal >= cornerlat[0] &&
			       latTestVal <= cornerlat[1]);


		    if (bndflag == 1)
		    {
			/*
			 * If boundary flag set test whether longitude value
			 * is outside region and then flip
			 */
			lonTest = (lonTestVal >= cornerlon[1] &&
				   lonTestVal <= cornerlon[0]);
			lonTest = 1 - lonTest;
		    }
		    else
		    {
			lonTest = (lonTestVal >= cornerlon[0] &&
				   lonTestVal <= cornerlon[1]);
		    }


		    /*
		     * If both longitude and latitude are within region set
		     * flag on for this track
		     */
		    if (lonTest + latTest == 2)
		    {
			flag[i] = 1;
			found = 1;
			break;
		    }
		}
	    }



	    /* ANYPOINT search */
	    /* --------------- */
	    if (mode == HDFE_ANYPOINT && rank > 1)
	    {
		free(lonArr);
		free(latArr);

		/* Allocate space for an entire single cross track */
		/* ----------------------------------------------- */
		lonArr = (char *) calloc(dims[1], sizeof(float64));
		if(lonArr == NULL)
		{ 
		    HEpush(DFE_NOSPACE,"SWregionl_index", __FILE__, __LINE__);
		    return(-1);
		}
		latArr = (char *) calloc(dims[1], sizeof(float64));
		if(latArr == NULL)
		{ 
		    HEpush(DFE_NOSPACE,"SWregionl_index", __FILE__, __LINE__);
		    free(lonArr);
		    return(-1);
		}

		/* Setup start and edge */
		/* -------------------- */
		anyStart[1] = 0;
		anyEdge[0] = 1;
		anyEdge[1] = dims[1];


		/* For each track ... */
		/* ------------------ */
		for (i = 0; i < edge[0]; i++)
		{

		    /* If cross track not in region (with MIDPOINT search ... */
		    /* ------------------------------------------------------ */
		    if (flag[i] == 0)
		    {
			/* Setup track start */
			/* ----------------- */
			anyStart[0] = i;


			/* Read in lon and lat values for cross track */
			/* ------------------------------------------ */
			status = SWreadfield(swathID, "Longitude",
					   anyStart, NULL, anyEdge, lonArr);
			status = SWreadfield(swathID, latName,
					   anyStart, NULL, anyEdge, latArr);



			/*
			 * If geolocation fields are FLOAT32 then cast each
			 * entry as FLOAT64
			 */
			if (nt == DFNT_FLOAT32)
			{
			    for (j = dims[1] - 1; j >= 0; j--)
			    {
				memcpy(&temp32, lonArr + 4 * j, 4);
				temp64 = (float64) temp32;
				memcpy(lonArr + 8 * j, &temp64, 8);

				memcpy(&temp32, latArr + 4 * j, 4);
				temp64 = (float64) temp32;
				memcpy(latArr + 8 * j, &temp64, 8);
			    }
			}


			/* For each value from Cross Track ... */
			/* ----------------------------------- */
			for (j = 0; j < dims[1]; j++)
			{
			    /* Read in single lon & lat values from buffers */
			    /* -------------------------------------------- */
			    memcpy(&lonTestVal, &lonArr[8 * j], 8);
			    memcpy(&latTestVal, &latArr[8 * j], 8);


			    /* If lon value > 180 convert to -180 - 180 range */
			    /* ---------------------------------------------- */
			    if (lonTestVal > 180)
			    {
				lonTestVal = lonTestVal - 360;
			    }

			    /* If Colatitude value convert to latitude value */
			    /* --------------------------------------------- */
			    if (statCoLat == 0)
			    {
				latTestVal = 90 - latTestVal;
			    }


			    /* Test if lat value is within range */
			    /* --------------------------------- */
			    latTest = (latTestVal >= cornerlat[0] &&
				       latTestVal <= cornerlat[1]);


			    if (bndflag == 1)
			    {
				/*
				 * If boundary flag set test whether
				 * longitude value is outside region and then
				 * flip
				 */
				lonTest = (lonTestVal >= cornerlon[1] &&
					   lonTestVal <= cornerlon[0]);
				lonTest = 1 - lonTest;
			    }
			    else
			    {
				lonTest = (lonTestVal >= cornerlon[0] &&
					   lonTestVal <= cornerlon[1]);
			    }


			    /*
			     * If both longitude and latitude are within
			     * region set flag on for this track
			     */
			    if (lonTest + latTest == 2)
			    {
				flag[i] = 1;
				found = 1;
				break;
			    }
			}
		    }
		}
	    }
	    /*
	    for (j1 = 0; j1 < edge[0]; j1++)
	      {
		idxrange[j1] = (int32) flag[j1];
	      }
	    */
	    /* If within region setup Region Structure */
	    /* --------------------------------------- */
	    if (found == 1)
	    {
		/* For all entries in SWXRegion array ... */
		/* -------------------------------------- */
		for (k = 0; k < NSWATHREGN; k++)
		{
		    /* If empty region ... */
		    /* ------------------- */
		    if (SWXRegion[k] == 0)
		    {
			/* Allocate space for region entry */
			/* ------------------------------- */
			SWXRegion[k] = (struct swathRegion *)
			    calloc(1, sizeof(struct swathRegion));
			if(SWXRegion[k] == NULL)
			{ 
			    HEpush(DFE_NOSPACE,"SWregionl_index", __FILE__, __LINE__);
			    return(-1);
			}

			/* Store file and swath ID */
			/* ----------------------- */
			SWXRegion[k]->fid = fid;
			SWXRegion[k]->swathID = swathID;


			/* Set Start & Stop Vertical arrays to -1 */
			/* -------------------------------------- */
			for (j = 0; j < 8; j++)
			{
			    SWXRegion[k]->StartVertical[j] = -1;
			    SWXRegion[k]->StopVertical[j] = -1;
			    SWXRegion[k]->StartScan[j] = -1;
			    SWXRegion[k]->StopScan[j] = -1;
			}


			/* Set region ID */
			/* ------------- */
			regionID = k;
			break;
		    }
		}
		if (k >= NSWATHREGN)
		  {
		    HEpush(DFE_GENAPP, "SWregionl_index", __FILE__, __LINE__);
		    HEreport(
			     "regionID exceeded NSWATHREGN.\n");
                    return (-1);
		  }

		/* Find start and stop of regions */
		/* ------------------------------ */

		/* Subtract previous flag value from current one */
		/* --------------------------------------------- */

		/*
		 * Transition points will have flag value (+1) start or
		 * (255 = (uint8) -1) stop of region
		 */
		for (i = edge[0]; i > 0; i--)
		{
		    flag[i] -= flag[i - 1];
		}


		for (i = 0; i <= edge[0]; i++)
		{
		    /* Start of region */
		    /* --------------- */
		    if (flag[i] == 1)
		    {
			/* Delyth Jones Moved the increment of the region down
			   to next if statement j = ++SWXRegion[k]->nRegions; */

			/* using temp value, if not equal to stop region
			   invalid region otherwise ok Delyth Jones */
			tmpVal = i+1;
		    }

		    /* End of region */
		    /* ------------- */
		    if (flag[i] == 255)
		    {
			if( tmpVal!=i )
			{
			    /* Increment (multiple) region counter */
			    /* ----------------------------------- */
			    j = ++SWXRegion[k]->nRegions;
			    
                            if (mapstatus == 2)
                            {
                               l = i;
                               if ((tmpVal-1) % 2 == 1)
                               {
                                  tmpVal = tmpVal + 1;
                               }

                               if ((l-1) % 2 == 0)
                               {
                                  l = l - 1;
                               }
                            }
			    SWXRegion[k]->StartRegion[j - 1] = tmpVal-1;
                            idxrange[0] = tmpVal - 1;
			    SWXRegion[k]->StopRegion[j - 1] = l - 1;
                            idxrange[1] = l - 1;
			    validReg = 0;
			}
		    }
		    
		}

	    }
	    free(lonArr);
	    free(latArr);
	    free(flag);
	}
    }
    if(validReg==0)
    {
	return (regionID);
    }
    else
    {
	return (-1);
    }
    
}



/*----------------------------------------------------------------------------|
|  BEGIN_PROLOG                                                               |
|                                                                             |
|  FUNCTION: SWdeftimeperiod                                                  |
|                                                                             |
|  DESCRIPTION: Finds swath cross tracks observed during time period and      |
|               returns  period ID                                            |
|                                                                             |
|               region ID                                                     |
|  DESCRIPTION:                                                               |
|                                                                             |
|                                                                             |
|  Return Value    Type     Units     Description                             |
|  ============   ======  =========   =====================================   |
|  periodID       int32               (Period ID) or (-1) if failed           |
|                                                                             |
|  INPUTS:                                                                    |
|  swathID        int32               Swath structure ID                      |
|  starttime      float64 TAI sec     Start of time period                    |
|  stoptime       float64 TAI sec     Stop of time period                     |
|  mode           int32               Search mode                             |
|                                     HDFE_MIDPOINT - Use midpoint of Xtrack  |
|                                     HDFE_ENDPOINT - Use endpoints of Xtrack |
|                                                                             |
|  OUTPUTS:                                                                   |
|             None                                                            |
|                                                                             |
|  NOTES:                                                                     |
|                                                                             |
|                                                                             |
|   Date     Programmer   Description                                         |
|  ======   ============  =================================================   |
|  Jun 96   Joel Gales    Original Programmer                                 |
|                                                                             |
|  END_PROLOG                                                                 |
-----------------------------------------------------------------------------*/
int32
SWdeftimeperiod(int32 swathID, float64 starttime, float64 stoptime,
		int32 mode)
{

    intn            i;		    /* Loop index */
    intn            j;		    /* Loop index */
    intn            k = 0;		    /* Loop index */
    intn            status;	    /* routine return status variable */
    intn            statTime;	    /* Status from SWfieldinfo for time */

    uint8           found = 0;	    /* Found flag */

    int32           fid;	    /* HDF-EOS file ID */
    int32           sdInterfaceID;  /* HDF SDS interface ID */
    int32           swVgrpID;	    /* Swath Vgroup ID */
    int32           rank;	    /* Rank of geolocation fields */
    int32           nt;		    /* Number type of geolocation fields */
    int32           dims[8];	    /* Dimensions of geolocation fields */
    int32           start[2];	    /* Start array (read) */
    int32           stride[2] = {1, 1};	/* Stride array (read) */
    int32           edge[2];	    /* Edge array (read) */
    int32           periodID = -1;  /* Period ID (return) */
    int32           dum;	    /* Dummy (loop) variable */

    float64         time64Test;	    /* Time test value */
    float64        *time64 = NULL;  /* Time data array */

    char            dimlist[256];   /* Dimension list (geolocation fields) */

    /* Check for valid swath ID */
    /* ------------------------ */
    status = SWchkswid(swathID, "SWdeftimeperiod", &fid, &sdInterfaceID,
		       &swVgrpID);

    if (status == 0)
    {
	/* Get "Time" field info */
	/* --------------------- */
	statTime = SWfieldinfo(swathID, "Time", &rank, dims, &nt, dimlist);
	if (statTime != 0)
	{
	    status = -1;
	    HEpush(DFE_GENAPP, "SWdeftimeperiod", __FILE__, __LINE__);
	    HEreport("\"Time\" field not found.\n");
	}

	if (status == 0)
	{
	    /* Search along entire "Track" dimension from beginning to end */
	    /* ----------------------------------------------------------- */
	    start[0] = 0;
	    edge[0] = dims[0];


	    /* If 1D geolocation fields then set mode to MIDPOINT */
	    /* -------------------------------------------------- */
	    if (rank == 1)
	    {
		mode = HDFE_MIDPOINT;
	    }


	    switch (mode)
	    {

		/* If MIDPOINT search single point in middle of "CrossTrack" */
		/* --------------------------------------------------------- */
	    case HDFE_MIDPOINT:

		start[1] = dims[1] / 2;
		edge[1] = 1;


		/* Allocate space for time data */
		/* ---------------------------- */
		time64 = (float64 *) calloc(edge[0], 8);
		if(time64 == NULL)
		{ 
		    HEpush(DFE_NOSPACE,"SWdeftimeperiod", __FILE__, __LINE__);
		    return(-1);
		}


		/* Read "Time" field */
		/* ----------------- */
		status = SWreadfield(swathID, "Time",
				     start, NULL, edge, time64);
		break;


		/* If ENDPOINT search 2 points at either end of "CrossTrack" */
		/* --------------------------------------------------------- */
	    case HDFE_ENDPOINT:
		start[1] = 0;
		stride[1] = dims[1] - 1;
		edge[1] = 2;


		/* Allocate space for time data */
		/* ---------------------------- */
		time64 = (float64 *) calloc(edge[0] * 2, 8);
		if(time64 == NULL)
		{ 
		    HEpush(DFE_NOSPACE,"SWdeftimeperiod", __FILE__, __LINE__);
		    return(-1);
		}

		/* Read "Time" field */
		/* ----------------- */
		status = SWreadfield(swathID, "Time",
				     start, stride, edge, time64);
		break;

	    }

            if (time64)
            {
                /* For each track (from top) ... */
                /* ----------------------------- */
                for (i = 0; i < edge[0]; i++)
                {
                    /* For each value from Cross Track ... */
                    /* ----------------------------------- */
                    for (j = 0; j < edge[1]; j++)
                    {

                        /* Get time test value */
                        /* ------------------- */
                        time64Test = time64[i * edge[1] + j];


                        /* If within time period ... */
                        /* ------------------------- */
                        if (time64Test >= starttime &&
                            time64Test <= stoptime)
                        {
                            /* Set found flag */
                            /* -------------- */
                            found = 1;


                            /* For all entries in SWXRegion array ... */
                            /* -------------------------------------- */
                            for (k = 0; k < NSWATHREGN; k++)
                            {
                                /* If empty region ... */
                                /* ------------------- */
                                if (SWXRegion[k] == 0)
                                {
                                    /* Allocate space for region entry */
                                    /* ------------------------------- */
                                    SWXRegion[k] = (struct swathRegion *)
                                        calloc(1, sizeof(struct swathRegion));
                                    if(SWXRegion[k] == NULL)
                                    { 
                                        HEpush(DFE_NOSPACE,"SWdeftimeperiod", __FILE__, __LINE__);
                                        return(-1);
                                    }

                                    /* Store file and swath ID */
                                    /* ----------------------- */
                                    SWXRegion[k]->fid = fid;
                                    SWXRegion[k]->swathID = swathID;


                                    /* Set number of isolated regions to 1 */
                                    /* ----------------------------------- */
                                    SWXRegion[k]->nRegions = 1;


                                    /* Set start of region to first track found */
                                    /* ---------------------------------------- */
                                    SWXRegion[k]->StartRegion[0] = i;


                                    /* Set Start & Stop Vertical arrays to -1 */
                                    /* -------------------------------------- */
                                    for (dum = 0; dum < 8; dum++)
                                    {
                                        SWXRegion[k]->StartVertical[dum] = -1;
                                        SWXRegion[k]->StopVertical[dum] = -1;
                                        SWXRegion[k]->StartScan[dum] = -1;
                                        SWXRegion[k]->StopScan[dum] = -1;
                                    }


                                    /* Set period ID */
                                    /* ------------- */
                                    periodID = k;

                                    break;	/* Break from "k" loop */
                                }
                            }
                        }
                        if (found == 1)
                        {
                            break;	/* Break from "j" loop */
                        }
                    }
                    if (found == 1)
                    {
                        break;	/* Break from "i" loop */
                    }
                }



                /* Clear found flag */
                /* ---------------- */
                found = 0;


                /* For each track (from bottom) ... */
                /* -------------------------------- */
                for (i = edge[0] - 1; i >= 0; i--)
                {
                    /* For each value from Cross Track ... */
                    /* ----------------------------------- */
                    for (j = 0; j < edge[1]; j++)
                    {

                        /* Get time test value */
                        /* ------------------- */
                        time64Test = time64[i * edge[1] + j];


                        /* If within time period ... */
                        /* ------------------------- */
                        if (time64Test >= starttime &&
                            time64Test <= stoptime)
                        {
                            /* Set found flag */
                            /* -------------- */
                            found = 1;

                            /* Set start of region to first track found */
                            /* ---------------------------------------- */
                            SWXRegion[k]->StopRegion[0] = i;

                            break;	/* Break from "j" loop */
                        }
                    }
                    if (found == 1)
                    {
                        break;	/* Break from "i" loop */
                    }
                }

                free(time64);
            }
	}
    }

    return (periodID);
}

/*----------------------------------------------------------------------------|
|  BEGIN_PROLOG                                                               |
|                                                                             |
|  FUNCTION: SWextractregion                                                  |
|                                                                             |
|  DESCRIPTION: Retrieves data from specified region.                         |
|                                                                             |
|                                                                             |
|  Return Value    Type     Units     Description                             |
|  ============   ======  =========   =====================================   |
|  status         intn                return status (0) SUCCEED, (-1) FAIL    |
|                                                                             |
|  INPUTS:                                                                    |
|  swathID        int32               Swath structure ID                      |
|  regionID       int32               Region ID                               |
|  fieldname      char                Fieldname                               |
|  externalflag   int32               External geolocation fields flag        |
|                                     HDFE_INTERNAL (0)                       |
|                                     HDFE_EXTERNAL (1)                       |
|                                                                             |
|  OUTPUTS:                                                                   |
|  buffer         void                Data buffer containing subsetted region |
|                                                                             |
|  NOTES:                                                                     |
|                                                                             |
|                                                                             |
|   Date     Programmer   Description                                         |
|  ======   ============  =================================================   |
|  Jun 96   Joel Gales    Original Programmer                                 |
|  Aug 96   Joel Gales    Add vertical subsetting                             |
|  Oct 96   Joel Gales    Mapping offset value not read from SWmapinfo        |
|  Dec 96   Joel Gales    Vert Subset overwriting data buffer                 |
|  Dec 96   Joel Gales    Add multiple vertical subsetting capability         |
|  Mar 97   Joel Gales    Add support for l_index mapping                       |
|  Jul 99   DaW 	  Add support for floating scene subsetting 	      |
|  Feb 03   Terry Haran/                                                      |
|           Abe Taaheri   Forced map offset to 0 so that data is extracted    |
|                         without offset consideration. This will preserve    |
|                         original mapping between geofields and the data     |
|                         field.                                              |
|                                                                             |
|  END_PROLOG                                                                 |
-----------------------------------------------------------------------------*/
intn
SWextractregion(int32 swathID, int32 regionID, const char *fieldname,
		int32 externalflag, VOIDP buffer)

{
    intn            i;		/* Loop index */
    intn            j;		/* Loop index */
    intn            k;		/* Loop index */
    intn            l;		/* Loop index */
    intn            status;	/* routine return status variable */
    intn            long_status = 3;	/* routine return status variable    */
                                        /* for longitude                     */
    intn	    land_status = 3;	/* Used for L7 float scene sub.      */
    intn            statMap = -1;	/* Status from SWmapinfo  */

    uint8           found = 0;		/* Found flag */
    uint8           vfound = 0;		/* Found flag for vertical subsetting*/
                                        /*  --- xhua                         */
    uint8	    scene_cnt = 0;	/* Used for L7 float scene sub.      */
    uint8           detect_cnt = 0;     /* Used to convert scan to scanline  */
                                        /*  L7 float scene sub.              */

    int32           fid;	/* HDF-EOS file ID */
    int32           sdInterfaceID;	/* HDF SDS interface ID */
    int32           swVgrpID;	/* Swath Vgroup ID */

    int32	    numtype = 0; /* Used for L7 float scene sub. */
    int32	    count = 0;   /* Used for L7 float scene sub. */
    int32           l_index = 0;	/* Geo Dim Index */
    int32           nDim;	/* Number of dimensions */
    int32           slen[64];	/* String length array */
    int32           dum;	/* Dummy variable */
    int32           offset = 0;	/* Mapping offset */
    int32           incr = 0;	/* Mapping increment */
    int32           nXtrk;	/* Number of cross tracks */
    int32           scan_shift = 0; /* Used to take out partial scans */
    int32           dumdims[8];	/* Dimensions from SWfieldinfo */
    int32           start[8];	/* Start array for data read */
    int32           edge[8];	/* Edge array for data read */
    int32           dims[8];	/* Dimensions */
    int32           rank = 0;	/* Field rank */
    int32           rk = 0;	/* Field rank */
    int32           ntype = 0;	/* Field number type */
    int32           bufOffset = 0;	/* Output buffer offset */
    int32           size;	/* Size of data buffer */
    int32           idxMapElem = -1;	/* Number of l_index map elements  */
    int32          *idxmap = NULL;	/* Pointer to l_index mapping array */

    int32	startscanline = 0;
    int32	stopscanline = 0;
    char	*dfieldlist = (char *)NULL;
    int32	strbufsize = 0;
    int32	dfrank[8];
    int32	numtype2[8];
    uint16	*buffer2 = (uint16 *)NULL;
    uint16	*tbuffer = (uint16 *)NULL;
    int32	dims2[8];
    int32	nt = 0;
    int32	startscandim = -1;
    int32	stopscandim = -1;
    int32	rank2 = 0;

    char            dimlist[256];	/* Dimension list */
    char            geodim[256];/* Geolocation field dimension list */
    char            tgeodim[256];/* Time field dimension list */
    char            dgeodim[256];/* Data field dimension list for subsetting */
    char            utlbuf[256];/* Utility buffer */
    char           *ptr[64];	/* String pointer array */



    /* Check for valid swath ID */
    /* ------------------------ */
    status = SWchkswid(swathID, "SWextractregion", &fid, &sdInterfaceID,
		       &swVgrpID);


    /* Check for valid region ID */
    /* ------------------------- */
    if (status == 0)
    {
	if (regionID < 0 || regionID >= NSWATHREGN)
	{
	    status = -1;
	    HEpush(DFE_RANGE, "SWextractregion", __FILE__, __LINE__);
	    HEreport("Invalid Region id: %d.\n", regionID);
	}
    }



    /* Check for active region ID */
    /* -------------------------- */
    if (status == 0)
    {
	if (SWXRegion[regionID] == 0)
	{
	    status = -1;
	    HEpush(DFE_GENAPP, "SWextractregion", __FILE__, __LINE__);
	    HEreport("Inactive Region ID: %d.\n", regionID);
	}
    }


   /* This code checks for the attribute detector_count */
   /* which is found in Landsat 7 files.  It is used    */
   /* for some of the loops.                            */
   /* ================================================= */
   if (status == 0 && SWXRegion[regionID]->scanflag == 1)
   {
      land_status = SWattrinfo(swathID, "detector_count", &numtype, &count);
      if (land_status == 0)
         land_status = SWreadattr(swathID, "detector_count", &detect_cnt);
   }

    /* Check that geo file and data file are same for INTERNAL subsetting */
    /* ------------------------------------------------------------------ */
    if (status == 0)
    {
	if (SWXRegion[regionID]->fid != fid && externalflag != HDFE_EXTERNAL)
	{
	    status = -1;
	    HEpush(DFE_GENAPP, "SWextractregion", __FILE__, __LINE__);
	    HEreport("Region is not defined for this file.\n");
	}
    }



    /* Check that geo swath and data swath are same for INTERNAL subsetting */
    /* -------------------------------------------------------------------- */
    if (status == 0)
    {
	if (SWXRegion[regionID]->swathID != swathID &&
	    externalflag != HDFE_EXTERNAL)
	{
	    status = -1;
	    HEpush(DFE_GENAPP, "SWextractregion", __FILE__, __LINE__);
	    HEreport("Region is not defined for this Swath.\n");
	}
    }



    /* Check for valid fieldname */
    /* ------------------------- */
    if (status == 0)
    {

	/* Get data field info */
	/* ------------------- */
	status = SWfieldinfo(swathID, fieldname, &rank,
			     dims, &ntype, dimlist);

	if (status != 0)
	{
	    status = -1;
	    HEpush(DFE_GENAPP, "SWextractregion", __FILE__, __LINE__);
	    HEreport("Field \"%s\" Not Found.\n", fieldname);
	}
    }


    /* No problems so proceed ... */
    /* -------------------------- */
    if (status == 0)
    {


	/* Initialize start and edge for all dimensions */
	/* -------------------------------------------- */
	for (j = 0; j < rank; j++)
	{
	    start[j] = 0;
	    edge[j] = dims[j];
	}


	/* Vertical Subset */
	/* --------------- */
	for (j = 0; j < 8; j++)
	{
	    /* If active vertical subset ... */
	    /* ----------------------------- */
	    if (SWXRegion[regionID]->StartVertical[j] != -1)
	    {

		/* Find vertical dimension within dimlist */
		/* -------------------------------------- */
		dum = EHstrwithin(SWXRegion[regionID]->DimNamePtr[j],
				  dimlist, ',');

		/* If dimension found ... */
		/* ---------------------- */
		if (dum != -1)
		{
		    /* Compute start and edge for vertical dimension */
		    /* --------------------------------------------- */
                    vfound = 1;                   /* xhua */
		    start[dum] = SWXRegion[regionID]->StartVertical[j];
		    edge[dum] = SWXRegion[regionID]->StopVertical[j] -
			SWXRegion[regionID]->StartVertical[j] + 1;
		}
		else
		{
		    /* Vertical dimension not found */
		    /* ---------------------------- */
		    status = -1;
		    HEpush(DFE_GENAPP, "SWextractregion", __FILE__, __LINE__);
		    HEreport("Vertical Dimension Not Found: \"%s\".\n",
			     SWXRegion[regionID]->DimNamePtr);
		}
	    }
	} /* End of Vertical Subset loop  */



	/* No problems so proceed ... */
	/* -------------------------- */
	if (status == 0)
	{
	    /* If non-vertical subset regions defined ... */
	    /* ------------------------------------------ */
	    if (SWXRegion[regionID]->nRegions > 0)    
	    {

		/* Get geolocation dimension name */
		/* ------------------------------ */
		status = SWfieldinfo(SWXRegion[regionID]->swathID,
				     "Longitude", &dum,
				     dumdims, &dum, geodim);
                long_status = status;

                /* If Time field being used, check for dimensions */
                /* ---------------------------------------------- */
                if (timeflag == 1)
                {
                   /* code change to fix time subset bug for Landsat7 */

                   status = SWfieldinfo(SWXRegion[regionID]->swathID,
                                        "Time", &dum,
                                        dumdims, &dum, tgeodim);
                   
                   if (strcmp(geodim, tgeodim) != 0)
                   {
                      strcpy(geodim, tgeodim);
                   }
                }
                timeflag = 0;

                /* If defscanregion being used, get dimensions    */
                /* of field being used                            */
                /* ---------------------------------------------- */
                if (SWXRegion[regionID]->scanflag == 1)
                {
                   (void) SWnentries(SWXRegion[regionID]->swathID,4,&strbufsize);
                   dfieldlist = (char *)calloc(strbufsize + 1, sizeof(char));
                   (void) SWinqdatafields(SWXRegion[regionID]->swathID,dfieldlist,dfrank,numtype2);
                   status = SWfieldinfo(SWXRegion[regionID]->swathID,dfieldlist,&dum,dumdims,&dum,dgeodim);

                   /* The dimensions have to be switched, because */
                   /* the mappings force a geodim and datadim     */
                   /* so to find the mapping, the dimensions must */
                   /* be switched, but the subsetting will still  */
                   /* be based on the correct dimensions          */
                   /* ------------------------------------------- */
                   if (strcmp(dgeodim,dimlist) != 0 || long_status == -1)
                   {
                      strcpy(geodim,dimlist);
                      strcpy(dimlist,dgeodim);
                   }
                }


		/* Get "Track" (first) Dimension from geo dimlist */
		/* ---------------------------------------------- */
		nDim = EHparsestr(geodim, ',', ptr, slen);
		geodim[slen[0]] = 0;


		/* Parse Data Field Dimlist & find mapping */
		/* --------------------------------------- */
		nDim = EHparsestr(dimlist, ',', ptr, slen);


		/* Loop through all dimensions and search for mapping */
		/* -------------------------------------------------- */
		for (i = 0; i < nDim; i++)
		{
		    memcpy(utlbuf, ptr[i], slen[i]);
		    utlbuf[slen[i]] = 0;
		    statMap = SWmapinfo(swathID, geodim, utlbuf,
					&offset, &incr);


                    /*
                     *  Force offset to 0.
                     *  We're not changing the mapping, so we want
                     *  the original offset to apply to the subsetted data.
                     *  Otherwise, bad things happen, such as subsetting
                     *  past the end of the original data, and being unable
                     *  to read the first <offset> elements of the
                     *  original data.
                     *  The offset is only important for aligning the
                     *  data with interpolated (incr > 0) or decimated
                     *  (incr < 0) geolocation information for the data.
                     */

                    offset = 0;


		    /* Mapping found */
		    /* ------------- */
		    if (statMap == 0)
		    {
			found = 1;
			l_index = i;
			break;
		    }
		}


		/* If mapping not found check for geodim within dimlist */
		/* ---------------------------------------------------- */
		if (found == 0)
		{
		    l_index = EHstrwithin(geodim, dimlist, ',');

		    /* Geo dimension found within subset field dimlist */
		    /* ----------------------------------------------- */
		    if (l_index != -1)
		    {
			found = 1;
			offset = 0;
			incr = 1;
		    }
		}



		/* If mapping not found check for l_indexed mapping */
		/* ---------------------------------------------- */
		if (found == 0)
		{
		    /* Get size of geo dim & allocate space of l_index mapping */
		    /* ----------------------------------------------------- */
		    dum = SWdiminfo(swathID, geodim);

                    /* For Landsat files, the l_index mapping has two values   */
                    /* for each point, a left and right point.  So for a 37  */
                    /* scene band file there are 2x2 points for each scene   */
                    /* meaning, 2x2x37 = 148 values.  The above function     */
                    /* only returns the number of values in the track        */
                    /* dimension.                                            */
                    /* ----------------------------------------------------- */
                    if(land_status == 0)
                       if(strcmp(fieldname, "Latitude") == 0 || 
                          strcmp(fieldname, "Longitude") == 0)
                       {
                          dum = dum * 2;
                       }
		    idxmap = (int32 *) calloc(dum, sizeof(int32));
		    if(idxmap == NULL)
		    { 
			HEpush(DFE_NOSPACE,"SWextractregion", __FILE__, __LINE__);
			return(-1);
		    }

		    /* Loop through all dimensions and search for mapping */
		    /* -------------------------------------------------- */
		    for (i = 0; i < nDim; i++)
		    {
			memcpy(utlbuf, ptr[i], slen[i]);
			utlbuf[slen[i]] = 0;

			idxMapElem =
			    SWidxmapinfo(swathID, geodim, utlbuf, idxmap);


			/* Mapping found */
			/* ------------- */
			if (idxMapElem != -1)
			{
			    found = 1;
			    l_index = i;
			    break;
			}
		    }
		}


		/* If regular mapping found ... */
		/* ---------------------------- */
		if (found == 1 && idxMapElem == -1)
		{
		    for (k = 0; k < SWXRegion[regionID]->nRegions; k++)
		    {
			if (k > 0)
			{
			    /* Compute size in bytes of previous region */
			    /* ---------------------------------------- */
			    size = edge[0];
			    for (j = 1; j < rank; j++)
			    {
				size *= edge[j];
			    }
			    size *= DFKNTsize(ntype);


			    /* Compute output buffer offset */
			    /* ---------------------------- */
			    bufOffset += size;
			}
			else
			{
			    /* Initialize output buffer offset */
			    /* ------------------------------- */
			    bufOffset = 0;
			}


			/* Compute number of cross tracks in region */
			/* ---------------------------------------- */
			nXtrk = SWXRegion[regionID]->StopRegion[k] -
			    SWXRegion[regionID]->StartRegion[k] + 1;


			/* Positive increment (geodim <= datadim) */
			/* -------------------------------------- */
			if (incr > 0)
			{
                           if (SWXRegion[regionID]->scanflag == 1)
                           {
                              start[l_index] = SWXRegion[regionID]->StartRegion[k]/incr;
                              if(SWXRegion[regionID]->band8flag == 2 || 
                                 SWXRegion[regionID]->band8flag == 3)
                              {
                                 start[l_index] = (SWXRegion[regionID]->StartRegion[k]+detect_cnt)/incr;
                                 status = SWfieldinfo(SWXRegion[regionID]->swathID,"scan_no",&rank,dims2,&nt,dimlist);
                                 buffer2 = (uint16 *)calloc(dims2[0], sizeof(uint16));
                                 status = SWreadfield(SWXRegion[regionID]->swathID,"scan_no",NULL,NULL,NULL,buffer2);
                                 if(incr == 1)
                                    start[l_index] = start[l_index] - (buffer2[0] * detect_cnt);
                                 else
                                    start[l_index] = start[l_index] - buffer2[0];
                                 free(buffer2);
                              }
                              scan_shift = nXtrk % incr;
                              if(scan_shift != 0)
                                 nXtrk = nXtrk - scan_shift;
			      edge[l_index] = nXtrk / incr;
                              if (nXtrk % incr != 0)
                                 edge[l_index]++;
                              if(long_status == -1 || incr == 1)
                              {
                                 if( detect_cnt == 0 )
                                     return -1;
                                 scan_shift = nXtrk % detect_cnt;
                                 if(scan_shift != 0)
                                    edge[l_index] = nXtrk - scan_shift;
                              }

                           }
                           else
                           {
			      start[l_index] = SWXRegion[regionID]->StartRegion[k] * incr + offset;
			      edge[l_index] = nXtrk * incr - offset;
                           }
			}
			else
			{
			    /* Negative increment (geodim > datadim) */
			    /* ------------------------------------- */
			    start[l_index] = SWXRegion[regionID]->StartRegion[k]
				/ (-incr) + offset;
			    edge[l_index] = nXtrk / (-incr);

			    /*
			     * If Xtrk not exactly divisible by incr, round
			     * edge to next highest integer
			     */

			    if (nXtrk % (-incr) != 0)
			    {
				edge[l_index]++;
			    }
			}


			/* Read Data into output buffer */
			/* ---------------------------- */
			status = SWreadfield(swathID, fieldname,
					     start, NULL, edge,
					     (uint8 *) buffer + bufOffset);
		    }
		}
		else if (found == 1 && idxMapElem != -1)
		{
		    /* Indexed Mapping */
		    /* --------------- */
		    for (k = 0; k < SWXRegion[regionID]->nRegions; k++)
		    {
			if (k > 0)
			{
			    /* Compute size in bytes of previous region */
			    /* ---------------------------------------- */
			    size = edge[0];
			    for (j = 1; j < rank; j++)
			    {
				size *= edge[j];
			    }
			    size *= DFKNTsize(ntype);


			    /* Compute output buffer offset */
			    /* ---------------------------- */
			    bufOffset += size;
			}
			else
			{
			    /* Initialize output buffer offset */
			    /* ------------------------------- */
			    bufOffset = 0;
			}


			/* Compute start & edge from l_index mappings */
			/* ---------------------------------------- */
                        if (SWXRegion[regionID]->scanflag == 1 &&
                            (strcmp(fieldname, "Latitude") == 0 ||
                             strcmp(fieldname, "Longitude") == 0))
                        {
                           if (land_status == 0)
                              status = SWreadattr(swathID, "scene_count", &scene_cnt);
                           startscanline = SWXRegion[regionID]->StartRegion[k];
                           stopscanline = SWXRegion[regionID]->StopRegion[k];
                           if(SWXRegion[regionID]->band8flag == 2 || SWXRegion[regionID]->band8flag == 3)
                           {
                               status = SWfieldinfo(swathID,"scan_no",&rk,dims2,&nt,dimlist);
                               tbuffer = (uint16 *)calloc(dims2[0], sizeof(uint16));
                               status =SWreadfield(swathID,"scan_no",NULL,NULL,NULL,tbuffer);
                               startscanline = startscanline - ((tbuffer[0] * detect_cnt) - detect_cnt);
                               stopscanline = stopscanline - ((tbuffer[0] * detect_cnt) - 1);
                           }
                           if(SWXRegion[regionID]->band8flag == 2 ||
                              SWXRegion[regionID]->band8flag == 3)
                           {
                              if(startscandim == -1)
                                 if(startscanline < idxmap[0])
                                 {
                                    startscandim = 0;
                                    start[l_index] = 0;
                                    if(stopscanline > idxmap[scene_cnt * 2 - 1])
                                    {
                                       stopscandim = scene_cnt*2 - startscandim;
                                       edge[l_index] = scene_cnt*2 - startscandim;
                                    }
                                 }
                           }
                           j = 0;
                           for (l = 0; l < scene_cnt; l++)
                           {
                              if(idxmap[j] <= startscanline && idxmap[j+1] >= startscanline)
                                 if(startscandim == -1)
                                 {
                                    start[l_index] = j;
                                    startscandim = j;
                                 }
                              if(idxmap[j] <= stopscanline && idxmap[j+1] >= stopscanline)
                                 if(startscandim != -1)
                                 {
                                    edge[l_index] = j - start[l_index] + 2;
                                    stopscandim = j - start[l_index] + 1;
                                 }
                              j = j + 2;
                           }
                           if(SWXRegion[regionID]->band8flag == 1 ||
                              SWXRegion[regionID]->band8flag == 2)
                           {
                              if(startscandim == -1)
                                 if(startscanline < idxmap[0])
                                 {
                                    startscandim = 0;
                                    start[l_index] = 0;
                                 }
                              if(stopscandim == -1)
                                 if(stopscanline > idxmap[scene_cnt * 2 - 1])
                                 {
                                    stopscandim = scene_cnt*2 - start[l_index];
                                    edge[l_index] = scene_cnt*2 - start[l_index];
                                 }
                           }
                           if(SWXRegion[regionID]->band8flag == 2)
                           {
                              if(startscandim == -1)
                                 if(startscanline > idxmap[j - 1])
                                 {
                                    status = SWfieldinfo(SWXRegion[regionID]->swathID,"scan_no",&rank2,dims2,&nt,dimlist);
                                    buffer2 = (uint16 *)calloc(dims2[0], sizeof(uint16));
                                    status = SWreadfield(SWXRegion[regionID]->swathID,"scan_no",NULL,NULL,NULL,buffer2);
                                    startscanline = startscanline - (buffer2[0] * detect_cnt);
                                    stopscanline = stopscanline - (buffer2[0] * detect_cnt);
                                    free(buffer2);
                                    j = 0;
                                    for (l = 0; l < scene_cnt; l++)
                                    {
                                       if(idxmap[j] <= startscanline && idxmap[j+1] >= startscanline)
                                       {
                                          start[l_index] = j;
                                       }
                                       if(idxmap[j] <= stopscanline && idxmap[j+1] >= stopscanline)
                                          edge[l_index] = j - start[l_index] + 2;
                                       j = j + 2;
                                       if(idxmap[j] == 0  || idxmap[j+1] == 0)
                                          l = scene_cnt;
                                    }
 
                                 }
                           }

                        }
                        else if(SWXRegion[regionID]->scanflag == 1 &&
                                (strcmp(fieldname, "scene_center_latitude") == 0 ||
                                 strcmp(fieldname, "scene_center_longitude") == 0))
                        {
                           if (land_status == 0)
                              status = SWreadattr(swathID, "scene_count", &scene_cnt);
                           startscanline = SWXRegion[regionID]->StartRegion[k];
                           stopscanline = SWXRegion[regionID]->StopRegion[k];
                           if(startscanline < idxmap[0])
                           {
                              startscandim = 0;
                              start[l_index] = 0;
                           }
                           for (l = 0; l < scene_cnt-1; l++)
                           {
                              if(idxmap[l] <= startscanline && idxmap[l+1] >= startscanline)
                                 if(startscandim == -1)
                                 {
                                    start[l_index] = l;
                                    startscandim = l;
                                 }
                              if(idxmap[l] <= stopscanline && idxmap[l+1] >= stopscanline)
                                 if(stopscandim == -1)
                                 {
                                    edge[l_index] = l - start[l_index] + 2;
                                    stopscandim = l + 1;
                                 }
                            }
                            if(stopscandim == -1)
                            {
                               if(stopscanline > idxmap[scene_cnt - 1])
                               {
                                  edge[l_index] = scene_cnt - start[l_index];
                                  stopscandim = scene_cnt - 1;
                               }
                            }

                            if(SWXRegion[regionID]->band8flag == 1)
                            {
                               if(stopscandim == -1)
                                  if(stopscanline > idxmap[scene_cnt - 1])
                                  {
                                     edge[l_index] = scene_cnt - start[l_index];
                                     stopscandim = scene_cnt -1;
                                  }
                            }
                            if(SWXRegion[regionID]->band8flag == 2 ||
                               SWXRegion[regionID]->band8flag == 3)
                            {
                               if(startscandim == -1)
                               {
                                  if(startscanline < idxmap[0])
                                  {
                                     startscandim = 0;
                                     start[l_index] = 0;
                                     edge[l_index] = stopscandim - startscandim + 1;
                                  }
                               }
                               if(startscandim == -1)
                               {
                                  startscanline = SWXRegion[regionID]->StartScan[k] * detect_cnt - detect_cnt;
                                  stopscanline = SWXRegion[regionID]->StopScan[k] * detect_cnt - 1;
                                  for (l = 0; l < scene_cnt-1; l++)
                                  {
                                     if(idxmap[l] <= startscanline && idxmap[l+1] >= startscanline)
                                        start[l_index] = l;
                                     if(idxmap[l] <= stopscanline && idxmap[l+1] >= stopscanline)
                                        edge[l_index] = l - start[l_index] + 1;
                                  }
                               }
                           }
                        }
                        else
                        {
                           if (SWXRegion[regionID]->scanflag == 1 && 
                               strcmp(fieldname,dfieldlist) == 0)
                           {
                              start[l_index] = SWXRegion[regionID]->StartRegion[k];
                              edge[l_index] = SWXRegion[regionID]->StopRegion[k] - 
                                             SWXRegion[regionID]->StartRegion[k] + 1;
                              if(SWXRegion[regionID]->band8flag == 2 ||
				 SWXRegion[regionID]->band8flag == 3 )
                              {
                                 status = SWfieldinfo(SWXRegion[regionID]->swathID,"scan_no",&rank,dims2,&nt,dimlist);
                                 buffer2 = (uint16 *)calloc(dims2[0], sizeof(uint16));
                                 status = SWreadfield(SWXRegion[regionID]->swathID,"scan_no",NULL,NULL,NULL,buffer2);
                                 start[l_index] = start[l_index] - (buffer2[0] * detect_cnt - detect_cnt);
                                 free(buffer2);
                              }
                           }
                           else
                           {
			      start[l_index] = idxmap[SWXRegion[regionID]->StartRegion[k]];

			      edge[l_index] = idxmap[SWXRegion[regionID]->StopRegion[k]] -
			                 idxmap[SWXRegion[regionID]->StartRegion[k]] + 1;
                           }
                        }
			/* Read Data into output buffer */
			/* ---------------------------- */
			status = SWreadfield(swathID, fieldname,
					     start, NULL, edge,
					     buffer);
                        if (SWXRegion[regionID]->scanflag == 1)
                        {
                           
                           if (strcmp(fieldname,"Longitude") == 0)
                           {
                              status = SWscan2longlat(swathID, fieldname, buffer, start, 
                                              edge, idxmap, startscanline, stopscanline);
                           }
                           if (strcmp(fieldname,"Latitude") == 0)
                           {
                              status = SWscan2longlat(swathID, fieldname, buffer, start, 
                                              edge, idxmap, startscanline, stopscanline);
                           }
                        }
		    }
		}
		else if(vfound == 1)                          /* Vertical subsetting */
                {                                             /* found previously,   */
                   status = SWreadfield(swathID, fieldname,   /* perform the vertical*/
                                        start, NULL, edge,    /* subsetting.         */
                                        (uint8 *) buffer);    /* -- xhua             */
                }
                else
		{
		    /* Mapping not found */
		    /* ----------------- */
		    status = -1; 
		    HEpush(DFE_GENAPP, "SWextractregion", __FILE__, __LINE__);
		    HEreport("Mapping Not Defined for \"%s\" Dimension.\n",
			     geodim);
		}                                           
	    }
	    else
	    {
		/* Read Data (Vert SS only) */
		/* ------------------------ */
		status = SWreadfield(swathID, fieldname,
				     start, NULL, edge,
				     (uint8 *) buffer);
	    }
	}
    }

    /* Free l_index mappings if applicable */
    /* --------------------------------- */
    if (idxmap != NULL)
    {
	free(idxmap);
    }
    if(dfieldlist != NULL)
       free(dfieldlist);

    return (status);
}


/*----------------------------------------------------------------------------|
|  BEGIN_PROLOG                                                               |
|                                                                             |
|  FUNCTION: SWscan2longlat                                                   |
|                                                                             |
|  DESCRIPTION:  Convert scanline to Long/Lat for floating scene subsetting.  |
|                This will calculate/interpolate the long/lat for a given     |
|                scanline.                                                    |
|                                                                             |
|                                                                             |
|  Return Value    Type     Units     Description                             |
|  ============   ======  =========   =====================================   |
|  status         intn                return status (0) SUCCEED, (-1) FAIL    |
|                                                                             |
|  INPUTS:                                                                    |
|  swathID        int32               Swath structure ID                      |
|  fieldname      char                Fieldname                               |
|  buffer	  void		      Values to update                        |
|  start	  int32		                                              |
|  edge		  int32							      |
|  idxmap	  int32 *	      Buffer of l_index mapping values          |
|  startscanline  int32		      Start of scan region		      |
|  stopscanline   int32		      Stop of scan region		      |
|                                                                             |
|  OUTPUTS:                                                                   |
|                                                                             |
|  NOTES:                                                                     |
|                                                                             |
|                                                                             |
|   Date     Programmer   Description                                         |
|  ======   ============  =================================================   |
|  Jul 99   DaW           Original Programmer                                 |
|                                                                             |
|  END_PROLOG                                                                 |
-----------------------------------------------------------------------------*/
static intn
SWscan2longlat(int32 swathID, const char *fieldname, VOIDP buffer, int32 start[], 
int32 edge[], int32 *idxmap, int32 startscanline, int32 stopscanline)
{

   enum corner {UL, UR, LL, LR};
   enum corner pos = UL;
   enum corner pos2 = UL;

   uint8	scene_cnt = 0;		/* Used to convert scan to scanline  */
                                        /*  L7 float scene sub.              */
   float32	*buffer2;
   float32	*bufferc;
   float32	deg2rad = (float32)(M_PI/180.00);

   float32	p1_long = 0.0;	/* point 1, longitude */
   float32	p2_long = 0.0;	/* point 2, longitude */
   float32	pi_long = 0.0;	/* interpolated point, longitude */
   int32	scanline_p1 = 0;

   float32	p1_lat = 0.0;	/* point 1, latitude */
   float32	p2_lat = 0.0;	/* point 2, latitude */
   float32	pi_lat = 0.0;	/* interpolated point, latitude */
   int32	scanline_p2 = 0;


   float32	x_p1 = 0.0;		/* Cartesian coordinates */
   float32	y_p1 = 0.0;		/* point 1               */
   float32	z_p1 = 0.0;

   float32	x_p2 = 0.0;		/* Cartesian coordinates */
   float32	y_p2 = 0.0;		/* point 2		 */
   float32	z_p2 = 0.0;

   float32	x_pi = 0.0;		/* Cartesian coordinates */
   float32	y_pi = 0.0;		/* interpolated point    */
   float32	z_pi = 0.0;
   int32	scanline_pi = 0;

   intn		status = -1;

   int		i = 0;
   int		p1_long_l90_flag = 0;
   int		p1_long_g90_flag = 0;
   int		p2_long_l90_flag = 0;
   int		p2_long_g90_flag = 0;
   int		fieldflag = 0;

   int	numofval = 0;



   numofval = edge[0] * 2;


   buffer2 = (float32 *)calloc(numofval, sizeof(float32));
   bufferc = (float32 *)calloc(numofval, sizeof(float32));
   memmove(bufferc, buffer, numofval*sizeof(float32));

   (void) SWreadattr(swathID, "scene_count", &scene_cnt);

   if (strcmp(fieldname, "Longitude") == 0)
   {
      fieldflag = 1;
      status = SWreadfield(swathID, "Latitude", start, NULL, edge, buffer2);
   }
   else if (strcmp(fieldname, "Latitude") == 0)
   {
      fieldflag = 2;
      status = SWreadfield(swathID, "Longitude", start, NULL, edge, buffer2);
   }

   for(i=0; i<4; i++)
   {
      switch(pos)
      {
         case UL:
            if (fieldflag == 1)
            {
               p1_long = bufferc[0];
               p2_long = bufferc[2];
               p1_lat = buffer2[0];
               p2_lat = buffer2[2];
            }
            if (fieldflag == 2)
            {
               p1_long = buffer2[0];
               p2_long = buffer2[2];
               p1_lat = bufferc[0];
               p2_lat = bufferc[2];
            }
            scanline_p1 = idxmap[start[0]];
            scanline_p2 = idxmap[start[0]+1];
            scanline_pi = startscanline;
            pos = UR;
            break;
         case UR:
            if (fieldflag == 1)
            {
               p1_long = bufferc[1];
               p2_long = bufferc[3];
               p1_lat = buffer2[1];
               p2_lat = buffer2[3];
            }
            if (fieldflag == 2)
            {
               p1_long = buffer2[1];
               p2_long = buffer2[3];
               p1_lat = bufferc[1];
               p2_lat = bufferc[3];
            }
            scanline_p1 = idxmap[start[0]];
            scanline_p2 = idxmap[start[0]+1];
            scanline_pi = startscanline;
            pos = LL;
            break;
         case LL:
            if (fieldflag == 1)
            {
               p1_long = bufferc[numofval-4];
               p2_long = bufferc[numofval-2];
               p1_lat = buffer2[numofval-4];
               p2_lat = buffer2[numofval-2];
            }
            if (fieldflag == 2)
            {
               p1_long = buffer2[numofval-4];
               p2_long = buffer2[numofval-2];
               p1_lat = bufferc[numofval-4];
               p2_lat = bufferc[numofval-2];
            }
            scanline_p1 = idxmap[start[0] + edge[0] - 2];
            scanline_p2 = idxmap[start[0] + edge[0] - 1];
            scanline_pi = stopscanline;
            pos = LR;
            break;
         case LR:
            if (fieldflag == 1)
            {
               p1_long = bufferc[numofval-3];
               p2_long = bufferc[numofval-1];
               p1_lat = buffer2[numofval-3];
               p2_lat = buffer2[numofval-1];
            }
            if (fieldflag == 2)
            {
               p1_long = buffer2[numofval-3];
               p2_long = buffer2[numofval-1];
               p1_lat = bufferc[numofval-3];
               p2_lat = bufferc[numofval-1];
            }
            scanline_p1 = idxmap[start[0] + edge[0] - 2];
            scanline_p2 = idxmap[start[0] + edge[0] - 1];
            scanline_pi = stopscanline;
            break;
      }



   if (p1_long <= -90.0)
   {
      if (p2_long >= 90.0)
      {
         p1_long = p1_long + 180.0f;
         p2_long = p2_long - 180.0f;
         p1_long_l90_flag = 2;
      }
      else
      {
         p1_long = p1_long + 180.0f;
         p1_long_l90_flag = 1;
      }
   }
   if (p1_long >= 90.0 && p1_long_l90_flag != 2)
   {
      if(p2_long <= -90.0)
      {
         p1_long = p1_long - 180.0f;
         p2_long = p2_long + 180.0f;
         p1_long_g90_flag = 2;
      }
      else
      {
         p1_long = p1_long - 90.0f;
         p1_long_g90_flag = 1;
      }
   }
   if (p2_long <= -90.0)
   {
      if (p1_long < 0.0)
      {
         p2_long = p2_long + 90.0f;
         p1_long = p1_long + 90.0f;
         p2_long_l90_flag = 2;
      }
      else
      {
         p2_long = p2_long + 180.0f;
         p2_long_l90_flag = 1;
      }
   }
   if (p2_long >= 90.0 && p1_long_l90_flag != 2)
   {
      p2_long = p2_long - 90.0f;
      p2_long_g90_flag = 1;
   }


   x_p1 = (float)(RADOE * cos((p1_long*deg2rad)) * sin((p1_lat*deg2rad)));
   y_p1 = (float)(RADOE * sin((p1_long*deg2rad)) * sin((p1_lat*deg2rad)));
   z_p1 = (float)(RADOE * cos((p1_lat*deg2rad)));

   
   x_p2 = (float)(RADOE * cos((p2_long*deg2rad)) * sin((p2_lat*deg2rad)));
   y_p2 = (float)(RADOE * sin((p2_long*deg2rad)) * sin((p2_lat*deg2rad)));
   z_p2 = (float)(RADOE * cos((p2_lat*deg2rad)));

   x_pi = x_p1 + (x_p2 - x_p1)*(scanline_pi-scanline_p1)/(scanline_p2-scanline_p1);
   y_pi = y_p1 + (y_p2 - y_p1)*(scanline_pi-scanline_p1)/(scanline_p2-scanline_p1);
   z_pi = z_p1 + (z_p2 - z_p1)*(scanline_pi-scanline_p1)/(scanline_p2-scanline_p1); 

   if (fieldflag == 1)
   {
      pi_long = (float)(atan(y_pi/x_pi)*180.0/M_PI);
      if (p1_long_l90_flag == 1 || p2_long_l90_flag == 1)
      {
         pi_long = pi_long - 180.0f;
         p1_long_l90_flag = 0;
	 p2_long_l90_flag = 0;
      }
      if (p1_long_g90_flag == 1 || p2_long_g90_flag == 1)
      {
         pi_long = pi_long + 90.0f;
         p1_long_g90_flag = 0;
         p2_long_g90_flag = 0;
      }
      if (p1_long_l90_flag == 2)
      {
         if (pi_long > 0.0)
            pi_long = pi_long - 180.0f;
         else if (pi_long < 0.0)
            pi_long = pi_long + 180.0f;
         p1_long_l90_flag = 0;
      }
      if (p1_long_g90_flag == 2)
      {
         if (pi_long > 0.0)
            pi_long = pi_long - 180.0f;
         else if (pi_long < 0.0)
            pi_long = pi_long + 180.0f;
         p1_long_g90_flag = 0;
      }
      if (p2_long_l90_flag == 2)
      {
         pi_long = pi_long - 90.0f;
         p2_long_l90_flag = 0;
      }



      switch(pos2)
      {
      case UL:
         bufferc[0] = pi_long;
         pos2 = UR;
         break;
      case UR:
         bufferc[1] = pi_long;
         pos2 = LL;
         break;
      case LL:
         if(stopscanline > idxmap[scene_cnt*2 - 1])
            break;
         bufferc[numofval-2] = pi_long;
         pos2 = LR;
         break;
      case LR:
         if(stopscanline > idxmap[scene_cnt*2 - 1])
            break;
         bufferc[numofval-1] = pi_long;
         break;
      }

    }
    if (fieldflag == 2)
    {
      pi_lat = (float)(atan((sqrt(x_pi*x_pi + y_pi*y_pi)/z_pi))*180.0/M_PI);
      switch(pos2)
      {
      case UL:
         bufferc[0] = pi_lat;
         pos2 = UR;
         break;
      case UR:
         bufferc[1] = pi_lat;
         pos2 = LL;
         break;
      case LL:
         if(stopscanline > idxmap[scene_cnt*2 - 1])
            break;
         bufferc[numofval-2] = pi_lat;
         pos2 = LR;
         break;
      case LR:
         if(stopscanline > idxmap[scene_cnt*2 - 1])
            break;
         bufferc[numofval-1] = pi_lat;
         break;
      }
   }
   }
   memmove(buffer, bufferc, numofval*sizeof(float32));
   free(buffer2);
   free(bufferc);
   return(status);
}


/*----------------------------------------------------------------------------|
|  BEGIN_PROLOG                                                               |
|                                                                             |
|  FUNCTION: SWextractperiod                                                  |
|                                                                             |
|  DESCRIPTION: Retrieves data from specified period.                         |
|                                                                             |
|                                                                             |
|  Return Value    Type     Units     Description                             |
|  ============   ======  =========   =====================================   |
|  status         intn                return status (0) SUCCEED, (-1) FAIL    |
|                                                                             |
|  INPUTS:                                                                    |
|  swathID        int32               Swath structure ID                      |
|  periodID       int32               Period ID                               |
|  fieldname      char                Fieldname                               |
|  externalflag   int32               External geolocation fields flag        |
|                                     HDFE_INTERNAL (0)                       |
|                                     HDFE_EXTERNAL (1)                       |
|                                                                             |
|  OUTPUTS:                                                                   |
|  buffer         void                Data buffer containing subsetted region |
|                                                                             |
|  NOTES:                                                                     |
|                                                                             |
|                                                                             |
|   Date     Programmer   Description                                         |
|  ======   ============  =================================================   |
|  Jun 96   Joel Gales    Original Programmer                                 |
|  Jun 03   Abe Taaheri   added clearing timeflag if SWextractregion fails    |
|                                                                             |
|  END_PROLOG                                                                 |
-----------------------------------------------------------------------------*/
intn
SWextractperiod(int32 swathID, int32 periodID, const char *fieldname,
		int32 externalflag, VOIDP buffer)

{
    intn            status;	/* routine return status variable */

    timeflag = 1;

    /* Call SWextractregion routine */
    /* ---------------------------- */
    status = SWextractregion(swathID, periodID, fieldname, externalflag,
			     (char *) buffer);
    if (status != 0) timeflag = 0; /*clear timeflag if SWextractregion failed*/
    return (status);
}







/*----------------------------------------------------------------------------|
|  BEGIN_PROLOG                                                               |
|                                                                             |
|  FUNCTION: SWdupregion                                                      |
|                                                                             |
|  DESCRIPTION: Duplicates a region                                           |
|                                                                             |
|                                                                             |
|  Return Value    Type     Units     Description                             |
|  ============   ======  =========   =====================================   |
|  newregionID    int32               New region ID                           |
|                                                                             |
|  INPUTS:                                                                    |
|  oldregionID    int32               Old region ID                           |
|                                                                             |
|  OUTPUTS:                                                                   |
|             None                                                            |
|                                                                             |
|  NOTES:                                                                     |
|                                                                             |
|                                                                             |
|   Date     Programmer   Description                                         |
|  ======   ============  =================================================   |
|  Jan 97   Joel Gales    Original Programmer                                 |
|                                                                             |
|  END_PROLOG                                                                 |
-----------------------------------------------------------------------------*/
int32
SWdupregion(int32 oldregionID)
{
    intn            i;		/* Loop index */

    int32           newregionID = -1;	/* New region ID */


    /* Find first empty (inactive) region */
    /* ---------------------------------- */
    for (i = 0; i < NSWATHREGN; i++)
    {
	if (SWXRegion[i] == 0)
	{
	    /* Allocate space for new swath region entry */
	    /* ----------------------------------------- */
	    SWXRegion[i] = (struct swathRegion *)
		calloc(1, sizeof(struct swathRegion));
	    if(SWXRegion[i] == NULL)
	    { 
		HEpush(DFE_NOSPACE,"SWdupregion", __FILE__, __LINE__);
		return(-1);
	    }

	    /* Copy old region structure data to new region */
	    /* -------------------------------------------- */
	    *SWXRegion[i] = *SWXRegion[oldregionID];


	    /* Define new region ID */
	    /* -------------------- */
	    newregionID = i;

	    break;
	}
    }

    return (newregionID);
}


/*----------------------------------------------------------------------------|
|  BEGIN_PROLOG                                                               |
|                                                                             |
|  FUNCTION: SWregioninfo                                                     |
|                                                                             |
|  DESCRIPTION: Returns size of region in bytes                               |
|                                                                             |
|                                                                             |
|  Return Value    Type     Units     Description                             |
|  ============   ======  =========   =====================================   |
|  status         intn                return status (0) SUCCEED, (-1) FAIL    |
|                                                                             |
|  INPUTS:                                                                    |
|  swathID        int32               Swath structure ID                      |
|  regionID       int32               Region ID                               |
|  fieldname      char                Fieldname                               |
|                                                                             |
|                                                                             |
|  OUTPUTS:                                                                   |
|  ntype          int32               field number type                       |
|  rank           int32               field rank                              |
|  dims           int32               dimensions of field region              |
|  size           int32               size in bytes of field region           |
|                                                                             |
|  NOTES:                                                                     |
|                                                                             |
|                                                                             |
|   Date     Programmer   Description                                         |
|  ======   ============  =================================================   |
|  Jun 96   Joel Gales    Original Programmer                                 |
|  Aug 96   Joel Gales    Add vertical subsetting                             |
|  Dec 96   Joel Gales    Add multiple vertical subsetting capability         |
|  Mar 97   Joel Gales    Add support for l_index mapping                       |
|  Jul 99   DaW           Add support for floating scene subsetting           |
|                                                                             |
|  END_PROLOG                                                                 |
-----------------------------------------------------------------------------*/
intn
SWregioninfo(int32 swathID, int32 regionID, const char *fieldname,
	     int32 * ntype, int32 * rank, int32 dims[], int32 * size)

{
    intn            i;		/* Loop index */
    intn            j;		/* Loop index */
    intn            k;		/* Loop index */
    intn            l = 0;		/* Loop index */
    intn            status;	/* routine return status variable */
    intn            long_status = 3;	/* routine return status variable for longitude */
    intn            land_status = 3;    /* Used for L7 float scene sub.      */
    intn            statMap = -1;   /* Status from SWmapinfo  */
    
    uint8           found = 0;	/* Found flag */
    uint8           detect_cnt = 0;	/* Used for L7 float scene sub.      */

    int32           numtype = 0; /* Used for L7 float scene sub. */
    int32           count = 0;   /* Used for L7 float scene sub. */


    int32           fid;	/* HDF-EOS file ID */
    int32           sdInterfaceID;	/* HDF SDS interface ID */
    int32           swVgrpID;	/* Swath Vgroup ID */

    int32           l_index = 0;	/* Geo Dim Index */
    int32           nDim;	/* Number of dimensions */
    int32           slen[64];	/* String length array */
    int32           dum;	/* Dummy variable */
    int32           incr = 0;	/* Mapping increment */
    int32           nXtrk = 0;	/* Number of cross tracks */
    int32	    scan_shift = 0; /* Used to take out partial scans */
    int32	    startscandim = -1;    /* Used for floating scene region size */
    int32	    stopscandim = -1;    /* Used for floating scene region size */
    int32           dumdims[8];	/* Dimensions from SWfieldinfo */
    int32           idxMapElem = -1;	/* Number of l_index map elements  */
    int32          *idxmap = NULL;	/* Pointer to l_index mapping array */
    int32	    datafld = 0;

   uint8	scene_cnt = 0;		/* Number of scenes in swath */
   int32	startscanline = 0;
   int32	stopscanline = 0;
   char		*dfieldlist = (char *)NULL;
   int32	strbufsize = 0;
   int32	dfrank[8];
   int32	numtype2[8];
   int32	rank2 = 0;
   int32	rk = 0;
   int32	dims2[8];
   int32	nt = 0;
   uint16	*buffer2 = (uint16 *)NULL;
   uint16	*tbuffer = (uint16 *)NULL;

    char            dimlist[256];	/* Dimension list */
    char            geodim[256];/* Geolocation field dimension list */
    char            tgeodim[256];/* Time Geolocation field dimension list */
    char            dgeodim[256];/* Data Subsetting field dimension list */
    char            utlbuf[256];/* Utility buffer */
    char           *ptr[64];	/* String pointer array */
    static const char errMesg[] = "Vertical Dimension Not Found: \"%s\".\n";



    /* Set region size to -1 */
    /* --------------------- */
    *size = -1;


    /* Check for valid swath ID */
    /* ------------------------ */
    status = SWchkswid(swathID, "SWregioninfo", &fid, &sdInterfaceID,
		       &swVgrpID);


    /* Check for valid region ID */
    /* ------------------------- */
    if (status == 0)
    {
	if (regionID < 0 || regionID >= NSWATHREGN)
	{
	    status = -1;
	    HEpush(DFE_RANGE, "SWregioninfo", __FILE__, __LINE__);
	    HEreport("Invalid Region id: %d.\n", regionID);
	}
    }



    /* Check for active region ID */
    /* -------------------------- */
    if (status == 0)
    {
	if (SWXRegion[regionID] == 0)
	{
	    status = -1;
	    HEpush(DFE_GENAPP, "SWregioninfo", __FILE__, __LINE__);
	    HEreport("Inactive Region ID: %d.\n", regionID);
	}
    }

   /* This code checks for the attribute detector_count */
   /* which is found in Landsat 7 files.  It is used    */
   /* for some of the loops.                            */
   /* ================================================= */
   if (status == 0 && SWXRegion[regionID]->scanflag == 1)
   {
      land_status = SWattrinfo(swathID, "detector_count", &numtype, &count);
      if (land_status == 0)
      {
         land_status = SWreadattr(swathID, "detector_count", &detect_cnt);
         land_status = SWreadattr(swathID, "scene_count", &scene_cnt);

      }
   }




    /* Check for valid fieldname */
    /* ------------------------- */
    if (status == 0)
    {
	/* Get data field info */
	/* ------------------- */
	status = SWfieldinfo(swathID, fieldname, rank,
			     dims, ntype, dimlist);

	if (status != 0)
	{
	    status = -1;
	    HEpush(DFE_GENAPP, "SWregioninfo", __FILE__, __LINE__);
	    HEreport("Field \"%s\" Not Found.\n", fieldname);
	}
    }



    /* No problems so proceed ... */
    /* -------------------------- */
    if (status == 0)
    {
	/* If non-vertical subset regions defined ... */
	/* ------------------------------------------ */
	if (SWXRegion[regionID]->nRegions > 0 || SWXRegion[regionID]->scanflag == 1)
	{

	    /* Get geolocation dimension name */
	    /* ------------------------------ */
	    status = SWfieldinfo(SWXRegion[regionID]->swathID,
				 "Longitude", &dum,
				 dumdims, &dum, geodim);
            long_status = status;

            /* If Time field being used, check for dimensions */
            /* ---------------------------------------------- */
            if (timeflag == 1)
            {
               /* code change to fix time subset bug for Landsat7 */

               status = SWfieldinfo(SWXRegion[regionID]->swathID,
                                    "Time", &dum,
                                    dumdims, &dum, tgeodim);
               
               if (strcmp(geodim, tgeodim) != 0)
               {
                  strcpy(geodim, tgeodim);
               }
            timeflag = 0;
            }

            /* If defscanregion being used, get dimensions    */
            /* of field being used                            */
            /* ---------------------------------------------- */
            if (SWXRegion[regionID]->scanflag == 1)
            {
               (void) SWnentries(SWXRegion[regionID]->swathID,4,&strbufsize);
               dfieldlist = (char *)calloc(strbufsize + 1, sizeof(char));
               (void) SWinqdatafields(SWXRegion[regionID]->swathID,dfieldlist,dfrank,numtype2);
               status = SWfieldinfo(SWXRegion[regionID]->swathID,dfieldlist,&dum,dumdims,&dum,dgeodim);

                  /* The dimensions have to be switched, because */
                  /* the mappings force a geodim and datadim     */
                  /* so to find the mapping, the dimensions must */
                  /* be switched, but the subsetting will still  */
                  /* be based on the correct dimensions          */
                  /* "long_status == -1" added for CAL file which   */
                  /* doesn't have a Traditional geolocation field   */
                  /* ---------------------------------------------- */
                  if (strcmp(dgeodim,dimlist) != 0 || long_status == -1)
                  {
                      strcpy(geodim,dimlist);
                      strcpy(dimlist,dgeodim);
                  }
            }


	    /* Get "Track" (first) Dimension from geo dimlist */
	    /* ---------------------------------------------- */
	    nDim = EHparsestr(geodim, ',', ptr, slen);
	    geodim[slen[0]] = 0;


	    /* Parse Data Field Dimlist & find mapping */
	    /* --------------------------------------- */
	    nDim = EHparsestr(dimlist, ',', ptr, slen);


	    /* Loop through all dimensions and search for mapping */
	    /* -------------------------------------------------- */
	    for (i = 0; i < nDim; i++)
	    {
		memcpy(utlbuf, ptr[i], slen[i]);
		utlbuf[slen[i]] = 0;
		statMap = SWmapinfo(swathID, geodim, utlbuf,
				    &dum, &incr);

		/* Mapping found */
		/* ------------- */
		if (statMap == 0)
		{
		    found = 1;
		    l_index = i;
		    break;
		}
	    }


	    /* If mapping not found check for geodim within dimlist */
	    /* ---------------------------------------------------- */
	    if (found == 0)
	    {
		l_index = EHstrwithin(geodim, dimlist, ',');

		/* Geo dimension found within subset field dimlist */
		/* ----------------------------------------------- */
		if (l_index != -1)
		{
		    found = 1;
		    incr = 1;
		}
	    }



	    /* If mapping not found check for l_indexed mapping */
	    /* ---------------------------------------------- */
	    if (found == 0)
	    {
		/* Get size of geo dim & allocate space of l_index mapping */
		/* ----------------------------------------------------- */
		dum = SWdiminfo(swathID, geodim);
		idxmap = (int32 *) calloc(dum, sizeof(int32));
		if(idxmap == NULL)
		{ 
		    HEpush(DFE_NOSPACE,"SWregioninfo", __FILE__, __LINE__);
		    return(-1);
		}

		/* Loop through all dimensions and search for mapping */
		/* -------------------------------------------------- */
		for (i = 0; i < nDim; i++)
		{
		    memcpy(utlbuf, ptr[i], slen[i]);
		    utlbuf[slen[i]] = 0;

		    idxMapElem = SWidxmapinfo(swathID, geodim, utlbuf, idxmap);


		    /* Mapping found */
		    /* ------------- */
		    if (idxMapElem != -1)
		    {
			found = 1;
			l_index = i;
			break;
		    }
		}
	    }


	    /* Regular Mapping Found */
	    /* --------------------- */
	    if (found == 1 && idxMapElem == -1)
	    {
		dims[l_index] = 0;

		/* Loop through all regions */
		/* ------------------------ */
		for (k = 0; k < SWXRegion[regionID]->nRegions; k++)
		{
		    /* Get number of cross tracks in particular region */
		    /* ----------------------------------------------- */
		    nXtrk = SWXRegion[regionID]->StopRegion[k] -
			SWXRegion[regionID]->StartRegion[k] + 1;


		    /* If increment is positive (geodim <= datadim) ... */
		    /* ------------------------------------------------ */
		    if (incr > 0)
		    {
                        if (SWXRegion[regionID]->scanflag == 1)
                        {
                            scan_shift = nXtrk % incr;
                            if(scan_shift != 0)
                               nXtrk = nXtrk - scan_shift;
                            dims[l_index] += nXtrk/incr;
                            if(long_status == -1 || incr == 1)
                            {
                               if( detect_cnt == 0 )
                                   return -1;
                               scan_shift = nXtrk % detect_cnt;
                               if(scan_shift != 0)
                                  dims[l_index] = nXtrk - scan_shift;
                            }
                        }
			else
                        {
			   dims[l_index] += nXtrk * incr;
                        }
		    }
		    else
		    {
			/* Negative increment (geodim > datadim) */
			/* ------------------------------------- */
			dims[l_index] += nXtrk / (-incr);

			/*
			 * If Xtrk not exactly divisible by incr, round dims
			 * to next highest integer
			 */
			if (nXtrk % (-incr) != 0)
			{
			    dims[l_index]++;
			}
		    }
		}
	    }
	    else if (found == 1 && idxMapElem != -1)
	    {

		/* Indexed Mapping */
		/* --------------- */

		dims[l_index] = 0;

		/* Loop through all regions */
		/* ------------------------ */
		for (k = 0; k < SWXRegion[regionID]->nRegions; k++)
		{
                   j = 0;
                   if(SWXRegion[regionID]->scanflag == 1)
                   {
                      startscanline = SWXRegion[regionID]->StartRegion[k];
                      stopscanline = SWXRegion[regionID]->StopRegion[k];
                      if (strcmp(fieldname,dfieldlist) == 0)
                      {
                         dims[l_index] = stopscanline - startscanline + 1;
                         datafld = 1;
                      }
                      if (strcmp(fieldname, "Latitude") == 0 ||
                          strcmp(fieldname, "Longitude") == 0)
                      {
                         if(SWXRegion[regionID]->band8flag == 2 || SWXRegion[regionID]->band8flag == 3)
                         {
                            status = SWfieldinfo(swathID,"scan_no",&rk,dims2,&nt,dimlist);
                            tbuffer = (uint16 *)calloc(dims2[0], sizeof(uint16));
                            status =SWreadfield(swathID,"scan_no",NULL,NULL,NULL,tbuffer);
                            startscanline = startscanline - ((tbuffer[0] * detect_cnt) - detect_cnt);
                            stopscanline = stopscanline - ((tbuffer[0] * detect_cnt) - 1);
                         }
                         if(SWXRegion[regionID]->band8flag == 2 ||
                            SWXRegion[regionID]->band8flag == 3)
                         {
                            if(startscandim == -1)
                               if(startscanline < idxmap[0])
                               {
                                  startscandim = 0;
                                  dims[l_index] = 0;
                                  if(stopscanline > idxmap[scene_cnt *2 - 1])
                                  {
                                     stopscandim = scene_cnt*2 - startscandim;
                                     dims[l_index] = scene_cnt*2 - startscandim;
                                  }
                               }
                         }
                         for (l = 0; l < scene_cnt; l++)
                         {
                            if(idxmap[j] <= startscanline && idxmap[j+1] >= startscanline)
                               if(startscandim == -1)
                               {
                                  dims[l_index] = j;
                                  startscandim = j;
                               }
                            if(idxmap[j] <= stopscanline && idxmap[j+1] >= stopscanline)
                               if(startscandim != -1)
                               {
                                  dims[l_index] = j - startscandim + 2;
                                  stopscandim = j + 1;
                               }
                            j = j + 2;
                            if(idxmap[j] == 0  || idxmap[j+1] == 0)
                               l = scene_cnt;
                         }
                         if(SWXRegion[regionID]->band8flag == 1 ||
                            SWXRegion[regionID]->band8flag == 2)
                         {
                            if(stopscandim == -1)
                               if(stopscanline > idxmap[scene_cnt * 2 - 1])
                               {
                                  stopscandim = scene_cnt*2 - dims[l_index];
                                  dims[l_index] = scene_cnt*2 - dims[l_index];
                               }
                         }
                         if(SWXRegion[regionID]->band8flag == 3)
                         {
                            if(startscandim == -1)
                               if(startscanline < idxmap[0])
                               {
                                  startscandim = 0;
                                  if(stopscandim != -1)
                                     dims[l_index] = stopscandim - startscandim + 1;
                               }
                         }
                         if(SWXRegion[regionID]->band8flag == 2)
                         {
                            if(startscandim == -1)
                               if(startscanline > idxmap[j - 1])
                               {
                                  status = SWfieldinfo(SWXRegion[regionID]->swathID,"scan_no",&rank2,dims2,&nt,dimlist);
                                  buffer2 = (uint16 *)calloc(dims2[0], sizeof(uint16));
                                  status = SWreadfield(SWXRegion[regionID]->swathID,"scan_no",NULL,NULL,NULL,buffer2);
                                  startscanline = startscanline - (buffer2[0] * detect_cnt);
                                  stopscanline = stopscanline - (buffer2[0] * detect_cnt);
                                  free(buffer2);
                                  j = 0;
                                  for (l = 0; l < scene_cnt; l++)
                                  {
                                     if(idxmap[j] <= startscanline && idxmap[j+1] >= startscanline)
                                     {
                                        dims[l_index] = j;
                                        startscandim = j;
                                     }
                                     if(idxmap[j] <= stopscanline && idxmap[j+1] >= stopscanline)
                                        dims[l_index] = j - startscandim + 2;
                                     j = j + 2;
                                     if(idxmap[j] == 0  || idxmap[j+1] == 0)
                                        l = scene_cnt;
                                  }

                               }
                         }
                      }
                      if (strcmp(fieldname, "scene_center_latitude") == 0 ||
                          strcmp(fieldname, "scene_center_longitude") == 0)
                      {
                         startscanline = SWXRegion[regionID]->StartRegion[k];
                         stopscanline = SWXRegion[regionID]->StopRegion[k];
                         if(startscanline < idxmap[0])
                         {
                            startscandim = 0;
                            dims[l_index] = 0;
                         }
                         for (l = 0; l < scene_cnt-1; l++)
                         {
                            if(idxmap[l] <= startscanline && idxmap[l+1] >= startscanline)
                               if(startscandim == -1)
                               {
                                  dims[l_index] = l;
                                  startscandim = l;
                               }
                            if(idxmap[l] <= stopscanline && idxmap[l+1] >= stopscanline)
                            {
                               dims[l_index] = l - startscandim + 2;
                               stopscandim = l + 1;
                            }
                         }
                         if(stopscandim == -1)
                         {
                            if(stopscanline > idxmap[scene_cnt - 1])
                            {
                               dims[l_index] = scene_cnt - startscandim;
                               stopscandim = scene_cnt - 1;
                            }
                         }
                         if(SWXRegion[regionID]->band8flag == 1)
                         {
                            if(stopscandim == -1)
                               if(stopscanline > idxmap[scene_cnt - 1])
                               {
                                  dims[l_index] = scene_cnt - startscandim;
                                  stopscandim = scene_cnt - 1;
                               }
                         }
                         if(SWXRegion[regionID]->band8flag == 2 ||
                            SWXRegion[regionID]->band8flag == 3)
                         {
                            if(startscandim == -1)
                            {
                               if(startscanline < idxmap[0])
                               {
                                  startscandim = 0;
                                  dims[l_index] = stopscandim - startscandim + 1;
                               }
                            }
                            if(startscandim == -1)
                            {
                               startscanline = SWXRegion[regionID]->StartScan[k] * detect_cnt;
                               stopscanline = SWXRegion[regionID]->StopScan[k] * detect_cnt;
                               for (l = 0; l < scene_cnt-1; l++)
                               {
                                  if(idxmap[l] <= startscanline && idxmap[l+1] >= startscanline)
                                     dims[l_index] = l;
                                  if(idxmap[l] <= stopscanline && idxmap[l+1] >= stopscanline)
                                     dims[l_index] = l - dims[l_index] + 1;
                               }
                            }
                         }
                      }
                   }
                   else
                   {
                      if (datafld != 1)
                      {
		         /* Get number of cross tracks in particular region */
		         /* ----------------------------------------------- */
		         nXtrk = idxmap[SWXRegion[regionID]->StopRegion[k]] -
			         idxmap[SWXRegion[regionID]->StartRegion[k]] + 1;

		         dims[l_index] += nXtrk;
                      }
                    }
		}
	    }
	    else
	    {
		/* Mapping not found */
		/* ----------------- */
	        status = -1;  
		HEpush(DFE_GENAPP, "SWregioninfo",
		       __FILE__, __LINE__);
		HEreport(
			 "Mapping Not Defined for \"%s\" Dimension.\n",
			 geodim);
	    }
	}



	/* Vertical Subset */
	/* --------------- */
	if (status == 0 || status == -1)  /* check the vertical subset in any case -- xhua */
	{
	    for (j = 0; j < 8; j++)
	    {
		/* If active vertical subset ... */
		/* ----------------------------- */
		if (SWXRegion[regionID]->StartVertical[j] != -1)
		{

		    /* Find vertical dimension within dimlist */
		    /* -------------------------------------- */
		    l_index = EHstrwithin(SWXRegion[regionID]->DimNamePtr[j],
					dimlist, ',');

		    /* If dimension found ... */
		    /* ---------------------- */
		    if (l_index != -1)
		    {
			/* Compute dimension size */
			/* ---------------------- */
			dims[l_index] =
			    SWXRegion[regionID]->StopVertical[j] -
			    SWXRegion[regionID]->StartVertical[j] + 1;
		    }
		    else
		    {
			/* Vertical dimension not found */
			/* ---------------------------- */
			status = -1;
			*size = -1;
			HEpush(DFE_GENAPP, "SWregioninfo", __FILE__, __LINE__);
			HEreport(errMesg, SWXRegion[regionID]->DimNamePtr[j]);
		    }
		}
	    }



	    /* Compute size of region data buffer */
	    /* ---------------------------------- */
	    if (status == 0)
	    {
                if(idxMapElem == 1 && SWXRegion[regionID]->scanflag == 1 && land_status == 0)
                {
                    if(startscandim == dims[0])
                       dims[0] = scene_cnt*2 - startscandim;
                }

		/* Compute number of total elements */
		/* -------------------------------- */
		*size = dims[0];
		for (j = 1; j < *rank; j++)
		{
		    *size *= dims[j];
		}

		/* Multiply by size in bytes of numbertype */
		/* --------------------------------------- */
		*size *= DFKNTsize(*ntype);
	    }
	}
    }



    /* Free l_index mappings if applicable */
    /* --------------------------------- */
    if (idxmap != NULL)
    {
	free(idxmap);
    }
    if(dfieldlist != NULL)
       free(dfieldlist);

    return (status);
}



/*----------------------------------------------------------------------------|
|  BEGIN_PROLOG                                                               |
|                                                                             |
|  FUNCTION: SWperiodinfo                                                     |
|                                                                             |
|  DESCRIPTION: Returns size in bytes of region                               |
|                                                                             |
|                                                                             |
|  Return Value    Type     Units     Description                             |
|  ============   ======  =========   =====================================   |
|  status         intn                return status (0) SUCCEED, (-1) FAIL    |
|                                                                             |
|  INPUTS:                                                                    |
|  swathID        int32               Swath structure ID                      |
|  periodID       int32               Period ID                               |
|  fieldname      char                Fieldname                               |
|                                                                             |
|                                                                             |
|  OUTPUTS:                                                                   |
|  ntype          int32               field number type                       |
|  rank           int32               field rank                              |
|  dims           int32               dimensions of field region              |
|  size           int32               size in bytes of field region           |
|                                                                             |
|  NOTES:                                                                     |
|                                                                             |
|                                                                             |
|   Date     Programmer   Description                                         |
|  ======   ============  =================================================   |
|  Jun 96   Joel Gales    Original Programmer                                 |
|  Jun 03   Abe Taaheri   added clearing timeflag if SWregioninfo fails       |
|                                                                             |
|  END_PROLOG                                                                 |
-----------------------------------------------------------------------------*/
intn
SWperiodinfo(int32 swathID, int32 periodID, const char *fieldname,
	     int32 * ntype, int32 * rank, int32 dims[], int32 * size)
{
    intn            status;	/* routine return status variable */


    timeflag = 1;
    /* Call SWregioninfo */
    /* ----------------- */
    status = SWregioninfo(swathID, periodID, fieldname, ntype, rank,
			  dims, size);
    if (status != 0) timeflag = 0;/* clear timeflag if SWregioninfo failed */
    return (status);
}





/*----------------------------------------------------------------------------|
|  BEGIN_PROLOG                                                               |
|                                                                             |
|  FUNCTION: SWdefvrtregion                                                   |
|                                                                             |
|  DESCRIPTION: Finds elements of a monotonic field within a given range.     |
|                                                                             |
|                                                                             |
|  Return Value    Type     Units     Description                             |
|  ============   ======  =========   =====================================   |
|  regionID       int32               Region ID                               |
|                                                                             |
|  INPUTS:                                                                    |
|  swathID        int32               Swath structure ID                      |
|  regionID       int32               Region ID                               |
|  vertObj        char                Vertical object to subset               |
|  range          float64             Vertical subsetting range               |
|                                                                             |
|  OUTPUTS:                                                                   |
|             None                                                            |
|                                                                             |
|  NOTES:                                                                     |
|                                                                             |
|                                                                             |
|   Date     Programmer   Description                                         |
|  ======   ============  =================================================   |
|  Aug 96   Joel Gales    Original Programmer                                 |
|  Dec 96   Joel Gales    Add multiple vertical subsetting capability         |
|  May 97   Joel Gales    Check for supported field types                     |
|                                                                             |
|  END_PROLOG                                                                 |
-----------------------------------------------------------------------------*/


/* Macro to initialize swath region entry */
/* -------------------------------------- */

/*
 * 1) Find empty (inactive) region. 2) Allocate space for region entry. 3)
 * Store file ID and swath ID. 4) Set region ID. 5) Initialize vertical
 * subset entries to -1.
 */

#define SETSWTHREG \
\
for (k = 0; k < NSWATHREGN; k++) \
{ \
    if (SWXRegion[k] == 0) \
    { \
        SWXRegion[k] = (struct swathRegion *) \
	  calloc(1, sizeof(struct swathRegion)); \
	SWXRegion[k]->fid = fid; \
	SWXRegion[k]->swathID = swathID; \
	regionID = k; \
	for (j=0; j<8; j++) \
        { \
             SWXRegion[k]->StartVertical[j] = -1; \
             SWXRegion[k]->StopVertical[j]  = -1; \
             SWXRegion[k]->StartScan[j] = -1; \
             SWXRegion[k]->StopScan[j]  = -1; \
             SWXRegion[k]->band8flag  = -1; \
        } \
	break; \
     } \
}


/* Macro to fill vertical subset entry */
/* ----------------------------------- */

/*
 * 1) Find empty (inactive) vertical region. 2) Set start of vertical region.
 * 3) Allocate space for name of vertical dimension. 4) Write vertical
 * dimension name.
 */

#define FILLVERTREG \
for (j=0; j<8; j++) \
{ \
    if (SWXRegion[regionID]->StartVertical[j] == -1) \
    { \
	SWXRegion[regionID]->StartVertical[j] = i; \
	SWXRegion[regionID]->DimNamePtr[j] = \
	    (char *) malloc(slen + 1); \
	memcpy(SWXRegion[regionID]->DimNamePtr[j], \
	       dimlist, slen + 1); \
	break; \
    } \
} \



int32
SWdefvrtregion(int32 swathID, int32 regionID, const char *vertObj, float64 range[])
{
    intn            i;		/* Loop index */
    intn            j = 0;		/* Loop index */
    intn            k;		/* Loop index */
    intn            status;	/* routine return status variable */

    uint8           found = 0;	/* Found flag */

    int16           vertINT16;	/* Temporary INT16 variable */

    int32           fid;	/* HDF-EOS file ID */
    int32           sdInterfaceID;	/* HDF SDS interface ID */
    int32           swVgrpID;	/* Swath Vgroup ID */
    int32           slen;	/* String length */
    int32           rank;	/* Field rank */
    int32           nt;		/* Field numbertype */
    int32           dims[8];	/* Field dimensions */
    int32           size;	/* Size of numbertype in bytes */
    int32           vertINT32;	/* Temporary INT32 variable */

    float32         vertFLT32;	/* Temporary FLT32 variable */

    float64         vertFLT64;	/* Temporary FLT64 variable */

    char           *vertArr;	/* Pointer to vertical field data buffer */
    char            dimlist[256];	/* Dimension list */


    /* Check for valid swath ID */
    /* ------------------------ */
    status = SWchkswid(swathID, "SWdefvrtregion", &fid, &sdInterfaceID,
		       &swVgrpID);

    if (status == 0)
    {
	/* Copy first 4 characters of vertObj into dimlist */
	/* ----------------------------------------------- */
	memcpy(dimlist, vertObj, 4);
	dimlist[4] = 0;



	/* If first 4 characters of vertObj = "DIM:" ... */
	/* --------------------------------------------- */

	/* Vertical Object is dimension name */
	/* --------------------------------- */
	if (strcmp(dimlist, "DIM:") == 0)
	{
	    /* Get string length of vertObj (minus "DIM:) */
	    /* ------------------------------------------ */
	    slen = (int)strlen(vertObj) - 4;


	    /* If regionID = -1 then setup swath region entry */
	    /* ---------------------------------------------- */
	    if (regionID == -1)
	    {
		SETSWTHREG;
	    }


	    /* Find first empty (inactive) vertical subset entry */
	    /* ------------------------------------------------- */
	    for (j = 0; j < 8; j++)
	    {
		if (SWXRegion[regionID]->StartVertical[j] == -1)
		{
		    /* Store start & stop of vertical region */
		    /* ------------------------------------- */
		    SWXRegion[regionID]->StartVertical[j] = (int32) range[0];
		    SWXRegion[regionID]->StopVertical[j] = (int32) range[1];

		    /* Store vertical dimension name */
		    /* ----------------------------- */
		    SWXRegion[regionID]->DimNamePtr[j] =
			(char *) malloc(slen + 1);
		    if(SWXRegion[regionID]->DimNamePtr[j] == NULL)
		    { 
			HEpush(DFE_NOSPACE,"SWdefvrtregion", __FILE__, __LINE__);
			return(-1);
		    }
		    memcpy(SWXRegion[regionID]->DimNamePtr[j],
			   vertObj + 4, slen + 1);
		    break;
		}
	    }
	}
	else
	{

	    /* Vertical Object is fieldname */
	    /* ---------------------------- */


	    /* Check for valid fieldname */
	    /* ------------------------- */
	    status = SWfieldinfo(swathID, vertObj, &rank, dims, &nt,
				 dimlist);

	    if (status != 0)
	    {
		status = -1;
		HEpush(DFE_GENAPP, "SWdefvrtregion", __FILE__, __LINE__);
		HEreport("Vertical Field: \"%s\" not found.\n", vertObj);
	    }



	    /* Check for supported field types */
	    /* ------------------------------- */
	    if (nt != DFNT_INT16 &&
		nt != DFNT_INT32 &&
		nt != DFNT_FLOAT32 &&
		nt != DFNT_FLOAT64)
	    {
		status = -1;
		HEpush(DFE_GENAPP, "SWdefvrtregion", __FILE__, __LINE__);
		HEreport("Fieldtype: %d not supported for vertical subsetting.\n", nt);
	    }



	    /* Check that vertical dimension is 1D */
	    /* ----------------------------------- */
	    if (status == 0)
	    {
		if (rank != 1)
		{
		    status = -1;
		    HEpush(DFE_GENAPP, "SWdefvrtregion", __FILE__, __LINE__);
		    HEreport("Vertical Field: \"%s\" must be 1-dim.\n",
			     vertObj);
		}
	    }


	    /* If no problems then continue */
	    /* ---------------------------- */
	    if (status == 0)
	    {
		/* Get string length of vertical dimension */
		/* --------------------------------------- */
		slen = (int)strlen(dimlist);


		/* Get size in bytes of vertical field numbertype */
		/* ---------------------------------------------- */
		size = DFKNTsize(nt);


		/* Allocate space for vertical field */
		/* --------------------------------- */
		vertArr = (char *) calloc(dims[0], size);
		if(vertArr == NULL)
		{ 
		    HEpush(DFE_NOSPACE,"SWdefvrtregion", __FILE__, __LINE__);
		    return(-1);
		}

		/* Read vertical field */
		/* ------------------- */
		status = SWreadfield(swathID, vertObj,
				     NULL, NULL, NULL, vertArr);



		switch (nt)
		{
		case DFNT_INT16:

		    for (i = 0; i < dims[0]; i++)
		    {
			/* Get single element of vertical field */
			/* ------------------------------------ */
			memcpy(&vertINT16, vertArr + i * size, size);


			/* If within range ... */
			/* ------------------- */
			if (vertINT16 >= range[0] &&
			    vertINT16 <= range[1])
			{
			    /* Set found flag */
			    /* -------------- */
			    found = 1;


			    /* If regionID=-1 then setup swath region entry */
			    /* -------------------------------------------- */
			    if (regionID == -1)
			    {
				SETSWTHREG;
			    }


			    /* Fill-in vertical region entries */
			    /* ------------------------------- */
			    FILLVERTREG;

			    break;
			}
		    }


		    /* If found read from "bottom" of data field */
		    /* ----------------------------------------- */
		    if (found == 1)
		    {
			for (i = dims[0] - 1; i >= 0; i--)
			{
			    /* Get single element of vertical field */
			    /* ------------------------------------ */
			    memcpy(&vertINT16, vertArr + i * size, size);


			    /* If within range ... */
			    /* ------------------- */
			    if (vertINT16 >= range[0] &&
				vertINT16 <= range[1])
			    {
				/* Set end of vertical region */
				/* -------------------------- */
				SWXRegion[regionID]->StopVertical[j] = i;
				break;
			    }
			}
		    }
		    else
		    {
			/* No vertical entries within region */
			/* --------------------------------- */
			status = -1;
			HEpush(DFE_GENAPP, "SWdefvrtregion",
			       __FILE__, __LINE__);
			HEreport("No vertical field entries within region.\n");
		    }
		    break;


		case DFNT_INT32:

		    for (i = 0; i < dims[0]; i++)
		    {
			/* Get single element of vertical field */
			/* ------------------------------------ */
			memcpy(&vertINT32, vertArr + i * size, size);


			/* If within range ... */
			/* ------------------- */
			if (vertINT32 >= range[0] &&
			    vertINT32 <= range[1])
			{
			    /* Set found flag */
			    /* -------------- */
			    found = 1;


			    /* If regionID=-1 then setup swath region entry */
			    /* -------------------------------------------- */
			    if (regionID == -1)
			    {
				SETSWTHREG;
			    }


			    /* Fill-in vertical region entries */
			    /* ------------------------------- */
			    FILLVERTREG;

			    break;
			}
		    }


		    /* If found read from "bottom" of data field */
		    /* ----------------------------------------- */
		    if (found == 1)
		    {
			for (i = dims[0] - 1; i >= 0; i--)
			{
			    /* Get single element of vertical field */
			    /* ------------------------------------ */
			    memcpy(&vertINT32, vertArr + i * size, size);


			    /* If within range ... */
			    /* ------------------- */
			    if (vertINT32 >= range[0] &&
				vertINT32 <= range[1])
			    {
				/* Set end of vertical region */
				/* -------------------------- */
				SWXRegion[regionID]->StopVertical[j] = i;
				break;
			    }
			}
		    }
		    else
		    {
			/* No vertical entries within region */
			/* --------------------------------- */
			status = -1;
			HEpush(DFE_GENAPP, "SWdefvrtregion",
			       __FILE__, __LINE__);
			HEreport("No vertical field entries within region.\n");
		    }
		    break;


		case DFNT_FLOAT32:

		    for (i = 0; i < dims[0]; i++)
		    {
			/* Get single element of vertical field */
			/* ------------------------------------ */
			memcpy(&vertFLT32, vertArr + i * size, size);


			/* If within range ... */
			/* ------------------- */
			if (vertFLT32 >= range[0] &&
			    vertFLT32 <= range[1])
			{
			    /* Set found flag */
			    /* -------------- */
			    found = 1;


			    /* If regionID=-1 then setup swath region entry */
			    /* -------------------------------------------- */
			    if (regionID == -1)
			    {
				SETSWTHREG;
			    }


			    /* Fill-in vertical region entries */
			    /* ------------------------------- */
			    FILLVERTREG;

			    break;
			}
		    }


		    /* If found read from "bottom" of data field */
		    /* ----------------------------------------- */
		    if (found == 1)
		    {
			for (i = dims[0] - 1; i >= 0; i--)
			{
			    /* Get single element of vertical field */
			    /* ------------------------------------ */
			    memcpy(&vertFLT32, vertArr + i * size, size);


			    /* If within range ... */
			    /* ------------------- */
			    if (vertFLT32 >= range[0] &&
				vertFLT32 <= range[1])
			    {
				/* Set end of vertical region */
				/* -------------------------- */
				SWXRegion[regionID]->StopVertical[j] = i;
				break;
			    }
			}
		    }
		    else
		    {
			/* No vertical entries within region */
			/* --------------------------------- */
			status = -1;
			HEpush(DFE_GENAPP, "SWdefvrtregion",
			       __FILE__, __LINE__);
			HEreport("No vertical field entries within region.\n");
		    }
		    break;


		case DFNT_FLOAT64:

		    for (i = 0; i < dims[0]; i++)
		    {
			/* Get single element of vertical field */
			/* ------------------------------------ */
			memcpy(&vertFLT64, vertArr + i * size, size);


			/* If within range ... */
			/* ------------------- */
			if (vertFLT64 >= range[0] &&
			    vertFLT64 <= range[1])
			{
			    /* Set found flag */
			    /* -------------- */
			    found = 1;


			    /* If regionID=-1 then setup swath region entry */
			    /* -------------------------------------------- */
			    if (regionID == -1)
			    {
				SETSWTHREG;
			    }


			    /* Fill-in vertical region entries */
			    /* ------------------------------- */
			    FILLVERTREG;

			    break;
			}
		    }


		    /* If found read from "bottom" of data field */
		    /* ----------------------------------------- */
		    if (found == 1)
		    {
			for (i = dims[0] - 1; i >= 0; i--)
			{
			    /* Get single element of vertical field */
			    /* ------------------------------------ */
			    memcpy(&vertFLT64, vertArr + i * size, size);

			    /* If within range ... */
			    /* ------------------- */
			    if (vertFLT64 >= range[0] &&
				vertFLT64 <= range[1])
			    {
				/* Set end of vertical region */
				/* -------------------------- */
				SWXRegion[regionID]->StopVertical[j] = i;
				break;
			    }
			}
		    }
		    else
		    {
			/* No vertical entries within region */
			/* --------------------------------- */
			status = -1;
			HEpush(DFE_GENAPP, "SWdefvrtregion",
			       __FILE__, __LINE__);
			HEreport("No vertical field entries within region.\n");
		    }
		    break;

		}		/* End of switch */
		free(vertArr);
	    }
	}
    }


    /* Set regionID to -1 if bad return status */
    /* --------------------------------------- */
    if (status == -1)
    {
	regionID = -1;
    }


    return (regionID);
}



/*----------------------------------------------------------------------------|
|  BEGIN_PROLOG                                                               |
|                                                                             |
|  FUNCTION: SWdefscanregion                                                  |
|                                                                             |
|  DESCRIPTION: Initialize the region structure for Landsat 7 float scene     |
|               subset							      |
|                                                                             |
|                                                                             |
|  Return Value    Type     Units     Description                             |
|  ============   ======  =========   =====================================   |
|  regionID       int32               Region ID                               |
|                                                                             |
|  INPUTS:                                                                    |
|  swathID        int32               Swath structure ID                      |
|  fieldname      char                Field name to subset                    |
|  range          float64             subsetting range                        |
|  mode		  int32		      HDFE_ENDPOINT, HDFE_MIDPOINT or         |
|				      HDFE_ANYPOINT                           |
|                                                                             |
|  OUTPUTS:                                                                   |
|  regionID	  int32		      Region ID                               |
|                                                                             |
|  NOTES:                                                                     |
|                                                                             |
|                                                                             |
|   Date     Programmer   Description                                         |
|  ======   ============  =================================================   |
|  Jul 99   DaW 	  Original Programmer                                 |
|                                                                             |
|  END_PROLOG                                                                 |
-----------------------------------------------------------------------------*/
int32
SWdefscanregion(int32 swathID, const char *fieldname, float64 range[], CPL_UNUSED int32 mode)
{
    intn            j;		/* Loop index */
    intn            k;		/* Loop index */
    intn            status;	/* routine return status variable */
    intn            land_status = 3;	/* routine return status variable */
    intn	    band81flag = 0;
    intn	    band82flag = 0;
    intn	    band83flag = 0;
    uint8           detect_cnt = 0;     /* Used to convert scan to scanline  */
                                        /*  L7 float scene sub.              */
    uint8           scene_cnt = 0;


    int32           nmtype = 0; /* Used for L7 float scene sub. */
    int32           count = 0;   /* Used for L7 float scene sub. */
    int32           fid;	/* HDF-EOS file ID */
    int32           sdInterfaceID;	/* HDF SDS interface ID */
    int32           swVgrpID;	/* Swath Vgroup ID */
    int32           slen;	/* String length */
    int32	    dfrank[8];  /* data fields rank */
    int32           rank;	/* Field rank */
    int32	    numtype[8]; /* number type of data fields */
    int32           nt;		/* Field numbertype */
    int32           dims[8];	/* Field dimensions */
    int32           dims2[8];	/* Field dimensions */
    int32	    strbufsize = 0; /* string buffer size */
    int32	    tmprange0 = 0;


    uint16	    *buffer = (uint16 *)NULL;
    int32	    *idxmap = (int32 *)NULL;

    int32	    dimsize = 0;

    int32           regionID = -1;	/* Region ID (return) */

    float64	    scan[2] = {0,0};
    float64	    original_scan[2] = {0,0};

    char            dimlist[256];	/* Dimension list */
    char	    swathname[80];
    char	    *dfieldlist = (char *)NULL;  /* data field list  */
    char	    *tfieldname = (char *)NULL;  /* temp field buffer  */
    char	    *band81 = (char *)NULL;
    char	    *band82 = (char *)NULL;
    char	    *band83 = (char *)NULL;


    /* Check for valid swath ID */
    /* ------------------------ */
    status = SWchkswid(swathID, "SWdefscanregion", &fid, &sdInterfaceID,
		       &swVgrpID);

   /* This code checks for the attribute detector_count */
   /* which is found in Landsat 7 files.  It is used    */
   /* for some of the loops. The other code checks if   */
   /* one scan is requested.                            */
   /* ================================================= */
      land_status = SWattrinfo(swathID, "detector_count", &nmtype, &count);
      if (land_status == 0)
      {
         scan[0] = range[0];
         scan[1] = range[1];
         original_scan[0] = range[0];
         original_scan[1] = range[1];

         land_status = SWreadattr(swathID, "scene_count", &scene_cnt);
         land_status = SWreadattr(swathID, "detector_count", &detect_cnt);
         if (range[0] == range[1])
         {
            range[0] = range[0] * detect_cnt - detect_cnt;
            range[1] = range[0] + detect_cnt - 1;
         }
         else
         {
            range[0] = range[0] * detect_cnt - detect_cnt;
            range[1] = range[1] * detect_cnt - 1;
         }

         Vgetname(SWXSwath[0].IDTable, swathname);
         band81 = strstr(swathname, "B81");
         if (band81 != (char *)NULL)
            band81flag = 1;
         band82 = strstr(swathname, "B82");
         if (band82 != (char *)NULL)
            band82flag = 1;
         band83 = strstr(swathname, "B83");
         if (band83 != (char *)NULL)
            band83flag = 1;
      }


    /* If fieldname is null then subsetting Landsat 7 */
    /* floating scene. Get data field name, assume    */
    /* only one data field in swath                   */
    /* ---------------------------------------------- */

    if (fieldname == (char *)NULL)
    {
       (void) SWnentries(swathID, 4, &strbufsize);
       dfieldlist = (char *)calloc(strbufsize + 1, sizeof(char));
       (void) SWinqdatafields(swathID, dfieldlist, dfrank, numtype);
       tfieldname = (char *)calloc(strbufsize + 1, sizeof(char));
       strcpy(tfieldname, dfieldlist);
    }
    else
    {
       slen = (int)strlen(fieldname);
       tfieldname = (char *)calloc(slen + 1, sizeof(char));
       strcpy(tfieldname, fieldname);
    }

    /* Check for valid fieldname */
    /* ------------------------- */
    status = SWfieldinfo(swathID, tfieldname, &rank, dims, &nt,
	 dimlist);

    if (status != 0)
    {
	status = -1;
	HEpush(DFE_GENAPP, "SWdefscanregion", __FILE__, __LINE__);
	HEreport("Field: \"%s\" not found.\n", tfieldname);
    }


       /* Check if input range values are within range of */
       /* data field                                      */
       /* ----------------------------------------------- */
       if(status == 0)
       {
          status = SWfieldinfo(swathID, "scan_no", &rank, dims2, &nt, dimlist);
          buffer = (uint16 *)calloc(dims2[0], sizeof(uint16));
          status = SWreadfield(swathID,"scan_no", NULL, NULL, NULL, buffer);
          if(scan[0] > buffer[dims2[0]-1])
          {
             HEpush(DFE_GENAPP, "SWdefscanregion", __FILE__, __LINE__);
             HEreport("Range values not within bounds of data field\n");
             free(buffer);
             buffer = (uint16 *)NULL;
             if (dfieldlist != NULL)
                free(dfieldlist);
             free(tfieldname);
             return(-1);
          }
          if(scan[0] < buffer[0])
          {
             if(scan[1] < buffer[0])
             {
                HEpush(DFE_GENAPP, "SWdefscanregion", __FILE__, __LINE__);
                HEreport("Range values not within bounds of data field\n");
                free(buffer);
                buffer = (uint16 *)NULL;
                if (dfieldlist != NULL)
                   free(dfieldlist);
                free(tfieldname);
                return(-1);
             }
             else
             {
                scan[0] = buffer[0];
                range[0] = scan[0] * detect_cnt - detect_cnt;
             }
          }
          if(scan[1] > buffer[dims2[0] - 1])
          {
             scan[1] = buffer[dims2[0] - 1];
             range[1] = scan[1] * detect_cnt - 1;
          }
       }

       if(status == 0)
       {
          dimsize = SWdiminfo(swathID, "GeoTrack");
          if(dimsize > 0)
          {
             idxmap = (int32 *)calloc(dimsize, sizeof(int32));
             (void) SWidxmapinfo(swathID, "GeoTrack", "ScanLineTrack", idxmap);
             tmprange0 = (int32)range[0];
             if(band82flag != 1 && band83flag != 1)
             {
                if (range[1] > idxmap[scene_cnt*2 - 1])
                {
                   range[1] = idxmap[scene_cnt*2 - 1];
                   HEreport("Data length compared to geolocation length\n");
                }
             }
             if(band82flag == 1 || band83flag == 1)
             {
                tmprange0 = (int32)(range[0] - (buffer[0] * detect_cnt - detect_cnt));
             }
             if(tmprange0 >= idxmap[scene_cnt * 2 - 1])
             {
                HEpush(DFE_GENAPP, "SWdefscanregion", __FILE__, __LINE__);
                HEreport(
            "Range values not within bounds of Latitude/Longitude field(s)\n");
                if (dfieldlist != NULL)
                   free(dfieldlist);
                free(tfieldname);
                free(buffer);
                free(idxmap);
                return(-1);
             }
          }
       }

    if (status == 0)
    {
          slen = (int)strlen(tfieldname);

          SETSWTHREG;

	  /* Find first empty (inactive) vertical subset entry */
	  /* ------------------------------------------------- */
	  for (j = 0; j < 8; j++)
	  {
	     if (SWXRegion[regionID]->StartVertical[j] == -1)
	     {
		    /* Store start & stop of region          */
		    /* ------------------------------------- */
                SWXRegion[regionID]->StartScan[j] = (int32) original_scan[0];
                SWXRegion[regionID]->StopScan[j] = (int32) original_scan[1];
		    SWXRegion[regionID]->StartRegion[j] = (int32) range[0];
		    SWXRegion[regionID]->StopRegion[j] = (int32) range[1];
                    ++SWXRegion[regionID]->nRegions;
                    SWXRegion[regionID]->scanflag = 1;
                    if(band81flag == 1)
                       SWXRegion[regionID]->band8flag = 1;
                    if(band82flag == 1)
                       SWXRegion[regionID]->band8flag = 2;
                    if(band83flag == 1)
                       SWXRegion[regionID]->band8flag = 3;
                   break;
		}
	    }
       }


    /* Set regionID to -1 if bad return status */
    /* --------------------------------------- */
    if (status == -1)
    {
	regionID = -1;
    }

    if (dfieldlist != NULL)
       free(dfieldlist);
    free(tfieldname);
    if (buffer != NULL)
       free(buffer);
    if (idxmap != NULL)
    free(idxmap);

    return (regionID);
}


/*----------------------------------------------------------------------------|
|  BEGIN_PROLOG                                                               |
|                                                                             |
|  FUNCTION: SWsetfillvalue                                                   |
|                                                                             |
|  DESCRIPTION: Sets fill value for the specified field.                      |
|                                                                             |
|                                                                             |
|  Return Value    Type     Units     Description                             |
|  ============   ======  =========   =====================================   |
|  status         intn                return status (0) SUCCEED, (-1) FAIL    |
|                                                                             |
|  INPUTS:                                                                    |
|  swathID        int32               swath structure ID                      |
|  fieldname      char                field name                              |
|  fillval        void                fill value                              |
|                                                                             |
|  OUTPUTS:                                                                   |
|             None                                                            |
|                                                                             |
|  NOTES:                                                                     |
|                                                                             |
|                                                                             |
|   Date     Programmer   Description                                         |
|  ======   ============  =================================================   |
|  Jun 96   Joel Gales    Original Programmer                                 |
|                                                                             |
|  END_PROLOG                                                                 |
-----------------------------------------------------------------------------*/
intn
SWsetfillvalue(int32 swathID, const char *fieldname, VOIDP fillval)
{
    intn            status;	/* routine return status variable */

    int32           fid;	/* HDF-EOS file ID */
    int32           sdInterfaceID;	/* HDF SDS interface ID */
    int32           swVgrpID;	/* Swath root Vgroup ID */
    int32           sdid;	/* SDS id */
    int32           nt;		/* Number type */
    int32           dims[8];	/* Dimensions array */
    int32           dum;	/* Dummy variable */
    int32           solo;	/* "Solo" (non-merged) field flag */

    char            name[80];	/* Fill value "attribute" name */

    /* Check for valid swath ID and get SDS interface ID */
    status = SWchkswid(swathID, "SWsetfillvalue",
		       &fid, &sdInterfaceID, &swVgrpID);

    if (status == 0)
    {
	/* Get field info */
	status = SWfieldinfo(swathID, fieldname, &dum, dims, &nt, NULL);

	if (status == 0)
	{
	    /* Get SDS ID and solo flag */
	    status = SWSDfldsrch(swathID, sdInterfaceID, fieldname,
				 &sdid, &dum, &dum, &dum,
				 dims, &solo);

	    /* If unmerged field then call HDF set field routine */
	    if (solo == 1)
	    {
                /* status = */ SDsetfillvalue(sdid, fillval);
	    }

	    /*
	     * Store fill value in attribute.  Name is given by fieldname
	     * prepended with "_FV_"
	     */
	    strcpy(name, "_FV_");
	    strcat(name, fieldname);
	    status = SWwriteattr(swathID, name, nt, 1, fillval);
	}
	else
	{
	    HEpush(DFE_GENAPP, "SWsetfillvalue", __FILE__, __LINE__);
	    HEreport("Fieldname \"%s\" does not exist.\n", fieldname);
	}
    }
    return (status);
}





/*----------------------------------------------------------------------------|
|  BEGIN_PROLOG                                                               |
|                                                                             |
|  FUNCTION: SWgetfillvalue                                                   |
|                                                                             |
|  DESCRIPTION: Retrieves fill value for a specified field.                   |
|                                                                             |
|                                                                             |
|  Return Value    Type     Units     Description                             |
|  ============   ======  =========   =====================================   |
|  status         intn                return status (0) SUCCEED, (-1) FAIL    |
|                                                                             |
|  INPUTS:                                                                    |
|  swathID        int32               swath structure ID                      |
|  fieldname      char                field name                              |
|                                                                             |
|  OUTPUTS:                                                                   |
|  fillval        void                fill value                              |
|                                                                             |
|  NOTES:                                                                     |
|                                                                             |
|                                                                             |
|   Date     Programmer   Description                                         |
|  ======   ============  =================================================   |
|  Jun 96   Joel Gales    Original Programmer                                 |
|                                                                             |
|  END_PROLOG                                                                 |
-----------------------------------------------------------------------------*/
intn
SWgetfillvalue(int32 swathID, const char *fieldname, VOIDP fillval)
{
    intn            status;	/* routine return status variable */

    int32           nt;		/* Number type */
    int32           dims[8];	/* Dimensions array */
    int32           dum;	/* Dummy variable */

    char            name[80];	/* Fill value "attribute" name */

    /* Check for valid swath ID */
    status = SWchkswid(swathID, "SWgetfillvalue", &dum, &dum, &dum);

    if (status == 0)
    {
	/* Get field info */
	status = SWfieldinfo(swathID, fieldname, &dum, dims, &nt, NULL);

	if (status == 0)
	{
	    /* Read fill value attribute */
	    strcpy(name, "_FV_");
	    strcat(name, fieldname);
	    status = SWreadattr(swathID, name, fillval);
	}
	else
	{
	    HEpush(DFE_GENAPP, "SWgetfillvalue", __FILE__, __LINE__);
	    HEreport("Fieldname \"%s\" does not exist.\n", fieldname);
	}

    }
    return (status);
}


/*----------------------------------------------------------------------------|
|  BEGIN_PROLOG                                                               |
|                                                                             |
|  FUNCTION: SWdetach                                                         |
|                                                                             |
|  DESCRIPTION: Detaches swath structure and performs housekeeping            |
|                                                                             |
|                                                                             |
|  Return Value    Type     Units     Description                             |
|  ============   ======  =========   =====================================   |
|  status         intn                return status (0) SUCCEED, (-1) FAIL    |
|                                                                             |
|  INPUTS:                                                                    |
|  swathID        int32               swath structure ID                      |
|                                                                             |
|                                                                             |
|  OUTPUTS:                                                                   |
|             None                                                            |
|                                                                             |
|  NOTES:                                                                     |
|                                                                             |
|                                                                             |
|   Date     Programmer   Description                                         |
|  ======   ============  =================================================   |
|  Jun 96   Joel Gales    Original Programmer                                 |
|  Aug 96   Joel Gales    Cleanup Region External Structure                   |
|  Sep 96   Joel Gales    Setup dim names for SDsetdimnane in dimbuf1 rather  |
|                         than utlstr                                         |
|  Nov 96   Joel Gales    Call SWchkgdid to check for proper swath ID         |
|  Dec 96   Joel Gales    Add multiple vertical subsetting garbage collection |
|                                                                             |
|  END_PROLOG                                                                 |
-----------------------------------------------------------------------------*/
intn
SWdetach(int32 swathID)

{
    intn            i;		/* Loop index */
    intn            j;		/* Loop index */
    intn            k;		/* Loop index */
    intn            status = 0;	/* routine return status variable */
    intn            statusFill = 0;	/* return status from SWgetfillvalue */

    uint8          *buf;	/* Buffer for blank (initial) 1D records */

    int32           vdataID;	/* Vdata ID */
    int32          *namelen;	/* Pointer to name string length array */
    int32          *dimlen;	/* Pointer to dim string length array */
    int32           slen1[3];	/* String length array 1 */
    int32           slen2[3];	/* String length array 2 */
    int32           nflds;	/* Number of fields */
    int32           match[5];	/* Merged field match array */
    int32           cmbfldcnt;	/* Number of fields combined */
    int32           sdid;	/* SDS ID */
    int32           vgid;	/* Vgroup ID */
    int32           dims[3];	/* Dimension array */
    int32          *offset;	/* Pointer to merged field offset array */
    int32          *indvdims;	/* Pointer to merged field size array */
    int32           sdInterfaceID;	/* SDS interface ID */
    int32           sID;	/* Swath ID - offset */
    int32           nflds0;	/* Number of fields */
    int32          *namelen0;	/* Pointer to name string length array */
    int32           rank;	/* Rank of merged field */
    int32           truerank;	/* True rank of merged field */
    int32           idOffset = SWIDOFFSET;	/* Swath ID offset */
    int32           dum;	/* Dummy variable */

    char           *nambuf;	/* Pointer to name buffer */
    char          **nameptr;	/* Pointer to name string pointer array */
    char          **dimptr;	/* Pointer to dim string pointer array */
    char          **nameptr0;	/* Pointer to name string pointer array */
    char           *ptr1[3];	/* String pointer array */
    char           *ptr2[3];	/* String pointer array */
    char            dimbuf1[128];	/* Dimension buffer 1 */
    char            dimbuf2[128];	/* Dimension buffer 2 */
    char            swathname[VGNAMELENMAX + 1];	/* Swath name */
    char           *utlbuf;	/* Utility buffer */
    char            fillval[32];/* Fill value buffer */

    /* Check for proper swath ID and get SD interface ID */
    /* ------------------------------------------------- */
    status = SWchkswid(swathID, "SWdetach", &dum, &sdInterfaceID, &dum);

    if (status == 0)
    {
	/* Subtract off swath ID offset and get swath name */
	/* ----------------------------------------------- */
	sID = swathID % idOffset;
	Vgetname(SWXSwath[sID].IDTable, swathname);


	/* Create 1D "orphaned" fields */
	/* --------------------------- */
	i = 0;

	/* Find "active" entries in 1d combination array */
	/* --------------------------------------------- */
	while (SWX1dcomb[3 * i] != 0)
	{
	    /* For fields defined within swath... */
	    /* ---------------------------------- */
	    if (SWX1dcomb[3 * i + 1] == SWXSwath[sID].IDTable)
	    {
		/* Get dimension size and vdata ID */
		/* ------------------------------- */
		dims[0] = abs(SWX1dcomb[3 * i]);
		vdataID = SWX1dcomb[3 * i + 2];

		/* Get fieldname (= vdata name) */
		/* ---------------------------- */
		nambuf = (char *) calloc(VSNAMELENMAX + 1, 1);
		if(nambuf == NULL)
		{ 
		    HEpush(DFE_NOSPACE,"SWdetach", __FILE__, __LINE__);
		    return(-1);
		}

		VSgetname(vdataID, nambuf);

		/* Set field within vdata */
		/* ---------------------- */
		VSsetfields(vdataID, nambuf);

		/* Write (blank) records */
		/* --------------------- */
		buf = (uint8 *) calloc(VSsizeof(vdataID, nambuf), dims[0]);
		if(buf == NULL)
		{ 
		    HEpush(DFE_NOSPACE,"SWdetach", __FILE__, __LINE__);
		    free(nambuf);
		    return(-1);
		}
		VSwrite(vdataID, buf, dims[0], FULL_INTERLACE);

		free(buf);
		free(nambuf);

		/* Detach Vdata */
		/* ------------ */
		VSdetach(vdataID);
	    }
	    i++;
	}


	/* SDS combined fields */
	/* ------------------- */
	if (strlen(SWXSDname) == 0)
	{
	    nflds = 0;

	    /* Allocate "dummy" arrays so free() doesn't bomb later */
	    /* ---------------------------------------------------- */
	    nameptr = (char **) calloc(1, sizeof(char *));
	    if(nameptr == NULL)
	    { 
		HEpush(DFE_NOSPACE,"SWdetach", __FILE__, __LINE__);
		return(-1);
	    }
	    namelen = (int32 *) calloc(1, sizeof(int32));
	    if(namelen == NULL)
	    { 
		HEpush(DFE_NOSPACE,"SWdetach", __FILE__, __LINE__);
		free(nameptr);
		return(-1);
	    }
	    nameptr0 = (char **) calloc(1, sizeof(char *));
	    if(nameptr0 == NULL)
	    { 
		HEpush(DFE_NOSPACE,"SWdetach", __FILE__, __LINE__);
		free(nameptr);
		free(namelen);
		return(-1);
	    }
	    namelen0 = (int32 *) calloc(1, sizeof(int32));
	    if(namelen0 == NULL)
	    { 
		HEpush(DFE_NOSPACE,"SWdetach", __FILE__, __LINE__);
		free(nameptr);
		free(namelen);
		free(nameptr0);
		return(-1);
	    }
	    dimptr = (char **) calloc(1, sizeof(char *));
	    if(dimptr == NULL)
	    { 
		HEpush(DFE_NOSPACE,"SWdetach", __FILE__, __LINE__);
		free(nameptr);
		free(namelen);
		free(nameptr0);
		free(namelen0);
		return(-1);
	    }
	    dimlen = (int32 *) calloc(1, sizeof(int32));
	    if(dimlen == NULL)
	    { 
		HEpush(DFE_NOSPACE,"SWdetach", __FILE__, __LINE__);
		free(nameptr);
		free(namelen);
		free(nameptr0);
		free(namelen0);
		free(dimptr);
		return(-1);
	    }
	    offset = (int32 *) calloc(1, sizeof(int32));
	    if(offset == NULL)
	    { 
		HEpush(DFE_NOSPACE,"SWdetach", __FILE__, __LINE__);
		free(nameptr);
		free(namelen);
		free(nameptr0);
		free(namelen0);
		free(dimptr);
		free(dimlen);
		return(-1);
	    }
	    indvdims = (int32 *) calloc(1, sizeof(int32));
	    if(indvdims == NULL)
	    { 
		HEpush(DFE_NOSPACE,"SWdetach", __FILE__, __LINE__);
		free(nameptr);
		free(namelen);
		free(nameptr0);
		free(namelen0);
		free(dimptr);
		free(dimlen);
		free(offset);
		return(-1);		    
	    }
	}
	else
	{
	    /*
	     * "Trim Off" trailing "," and ";" in SWXSDname & SWXSDdims
	     * respectively
	     */
	    SWXSDname[strlen(SWXSDname) - 1] = 0;
	    SWXSDdims[strlen(SWXSDdims) - 1] = 0;


	    /* Get number of fields from SWXSDname string */
	    /* ------------------------------------------ */
	    nflds = EHparsestr(SWXSDname, ',', NULL, NULL);


	    /* Allocate space for various dynamic arrays */
	    /* ----------------------------------------- */
	    nameptr = (char **) calloc(nflds, sizeof(char *));
	    if(nameptr == NULL)
	    { 
		HEpush(DFE_NOSPACE,"SWdetach", __FILE__, __LINE__);
		return(-1);
	    }
	    namelen = (int32 *) calloc(nflds, sizeof(int32));
	    if(namelen == NULL)
	    { 
		HEpush(DFE_NOSPACE,"SWdetach", __FILE__, __LINE__);
		free(nameptr);
		return(-1);
	    }
	    nameptr0 = (char **) calloc(nflds, sizeof(char *));
	    if(nameptr0 == NULL)
	    { 
		HEpush(DFE_NOSPACE,"SWdetach", __FILE__, __LINE__);
		free(nameptr);
		free(namelen);
		return(-1);
	    }
	    namelen0 = (int32 *) calloc(nflds, sizeof(int32));
	    if(namelen0 == NULL)
	    { 
		HEpush(DFE_NOSPACE,"SWdetach", __FILE__, __LINE__);
		free(nameptr);
		free(namelen);
		free(nameptr0);
		return(-1);
	    }
	    dimptr = (char **) calloc(nflds, sizeof(char *));
	    if(dimptr == NULL)
	    { 
		HEpush(DFE_NOSPACE,"SWdetach", __FILE__, __LINE__);
		free(nameptr);
		free(namelen);
		free(nameptr0);
		free(namelen0);
		return(-1);
	    }
	    dimlen = (int32 *) calloc(nflds, sizeof(int32));
	    if(dimlen == NULL)
	    { 
		HEpush(DFE_NOSPACE,"SWdetach", __FILE__, __LINE__);
		free(nameptr);
		free(namelen);
		free(nameptr0);
		free(namelen0);
		free(dimptr);
		return(-1);
	    }
	    offset = (int32 *) calloc(nflds, sizeof(int32));
	    if(offset == NULL)
	    { 
		HEpush(DFE_NOSPACE,"SWdetach", __FILE__, __LINE__);
		free(nameptr);
		free(namelen);
		free(nameptr0);
		free(namelen0);
		free(dimptr);
		free(dimlen);
		return(-1);
	    }
	    indvdims = (int32 *) calloc(nflds, sizeof(int32));
	    if(indvdims == NULL)
	    { 
		HEpush(DFE_NOSPACE,"SWdetach", __FILE__, __LINE__);
		free(nameptr);
		free(namelen);
		free(nameptr0);
		free(namelen0);
		free(dimptr);
		free(dimlen);
		free(offset);
		return(-1);		    
	    }


	    /* Parse SWXSDname and SWXSDdims strings */
	    /* ------------------------------------- */
	    nflds = EHparsestr(SWXSDname, ',', nameptr, namelen);
	    nflds = EHparsestr(SWXSDdims, ';', dimptr, dimlen);
	}


	/* Loop through all the fields */
	/* --------------------------- */
	for (i = 0; i < nflds; i++)
	{
	    /* If active entry and field is within swath to be detached ... */
	    /* ------------------------------------------------------------ */
	    if (SWXSDcomb[5 * i] != 0 &&
		SWXSDcomb[5 * i + 3] == SWXSwath[sID].IDTable)
	    {
		nambuf = (char *) calloc(strlen(SWXSDname) + 1, 1);
		if(nambuf == NULL)
		{ 
		    HEpush(DFE_NOSPACE,"SWdetach", __FILE__, __LINE__);
		    return(-1);
		}
		utlbuf = (char *) calloc(2 * strlen(SWXSDname) + 7, 1);
		if(utlbuf == NULL)
		{ 
		    HEpush(DFE_NOSPACE,"SWdetach", __FILE__, __LINE__);
		    free(nambuf);
		    return(-1);
		}
		/* Zero out dimbuf1 */
		/* ---------------- */
		for (k = 0; k < (intn)sizeof(dimbuf1); k++)
		{
		    dimbuf1[k] = 0;
		}


		/* Load array to match, name & parse dims */
		/* -------------------------------------- */
		memcpy(match, &SWXSDcomb[5 * i], 20);
		memcpy(nambuf, nameptr[i], namelen[i]);

		memcpy(dimbuf1, dimptr[i], dimlen[i]);
		dum = EHparsestr(dimbuf1, ',', ptr1, slen1);


		/* Separate combined (first) dimension from others */
		/* ----------------------------------------------- */
		dimbuf1[slen1[0]] = 0;

		offset[0] = 0;
		indvdims[0] = abs(match[0]);

		/*
		 * Loop through remaining fields to check for matches with
		 * current one
		 */
		for (j = i + 1, cmbfldcnt = 0; j < nflds; j++)
		{
		    if (SWXSDcomb[5 * j] != 0)
		    {
			/* Zero out dimbuf2 */
			/* ---------------- */
			for (k = 0; k < (intn)sizeof(dimbuf2); k++)
			{
			    dimbuf2[k] = 0;
			}

			/*
			 * Parse the dimensions and separate first for this
			 * entry
			 */
			memcpy(dimbuf2, dimptr[j], dimlen[j]);
			dum = EHparsestr(dimbuf2, ',', ptr2, slen2);
			dimbuf2[slen2[0]] = 0;


			/*
			 * If 2nd & 3rd dimension values and names (1st and
			 * 2nd for rank=2 array), swath ID, and numbertype
			 * are equal, then these fields can be combined.
			 */
			if (match[1] == SWXSDcomb[5 * j + 1] &&
			    match[2] == SWXSDcomb[5 * j + 2] &&
			    match[3] == SWXSDcomb[5 * j + 3] &&
			    match[4] == SWXSDcomb[5 * j + 4] &&
			    strcmp(dimbuf1 + slen1[0] + 1,
				   dimbuf2 + slen2[0] + 1) == 0)
			{
			    /* Add to combined dimension size */
			    /* ------------------------------ */
			    match[0] += SWXSDcomb[5 * j];

			    /* Concatenate name */
			    /* ---------------- */
			    strcat(nambuf, ",");
			    memcpy(nambuf + strlen(nambuf),
				   nameptr[j], namelen[j]);

			    /*
			     * Increment number of merged fields, store
			     * individual dims and dim offsets
			     */
			    cmbfldcnt++;
			    indvdims[cmbfldcnt] = abs(SWXSDcomb[5 * j]);
			    offset[cmbfldcnt] = offset[cmbfldcnt - 1] +
				indvdims[cmbfldcnt - 1];

			    /* Delete this field from combination list */
			    /* --------------------------------------- */
			    SWXSDcomb[5 * j] = 0;
			}
		    }
		}


		/* Create SDS */
		/* ---------- */

		/* Parse names string */
		/* ------------------ */
		nflds0 = EHparsestr(nambuf, ',', nameptr0, namelen0);

		if (abs(match[0]) == 1)
		{
		    /* Two Dimensional Array (no merging has occurred) */
		    /* ---------------------------------------------- */
		    dims[0] = abs(match[1]);
		    dims[1] = abs(match[2]);

		    /* Create SDS */
		    /* ---------- */
		    rank = 2;
		    sdid = SDcreate(sdInterfaceID, nambuf,
				    SWXSDcomb[5 * i + 4], 2, dims);
		}
		else
		{
		    /* Three Dimensional Array */
		    /* ----------------------- */
		    dims[0] = abs(match[0]);
		    dims[1] = abs(match[1]);
		    dims[2] = abs(match[2]);

		    rank = 3;

		    /*
		     * If merged fields then form string consisting of
		     * "MRGFLD_" + 1st field in merge + ":" + entire merged
		     * field list and store in utlbuf. Then write to
		     * MergedField metadata section
		     */
		    if (cmbfldcnt > 0)
		    {
			strcpy(utlbuf, "MRGFLD_");
			memcpy(utlbuf + 7, nameptr0[0], namelen0[0]);
			utlbuf[7 + namelen0[0]] = 0;
			strcat(utlbuf, ":");
			strcat(utlbuf, nambuf);

			status = EHinsertmeta(sdInterfaceID, swathname, "s",
					      6L, utlbuf, NULL);
		    }
		    else
		    {
			/*
			 * If not merged field then store field name in
			 * utlbuf
			 */
			strcpy(utlbuf, nambuf);
		    }

		    /* Create SDS */
		    /* ---------- */
		    sdid = SDcreate(sdInterfaceID, utlbuf,
				    SWXSDcomb[5 * i + 4], 3, dims);


		    /*
		     * If merged field then store dimensions and offsets as
		     * SD attributes
		     */
		    if (cmbfldcnt > 0)
		    {
			SDsetattr(sdid, "Field Dims", DFNT_INT32,
				  cmbfldcnt + 1, (VOIDP) indvdims);

			SDsetattr(sdid, "Field Offsets", DFNT_INT32,
				  cmbfldcnt + 1, (VOIDP) offset);
		    }
		}



		/* Register Dimensions in SDS */
		/* -------------------------- */
		for (k = 0; k < rank; k++)
		{
		    if (rank == 2)
		    {
			/* Copy k+1th dimension into dimbuf2 if rank = 2 */
			/* --------------------------------------------- */
			memcpy(dimbuf2, ptr1[k + 1], slen1[k + 1]);
			dimbuf2[slen1[k + 1]] = 0;
		    }
		    else
		    {
			/* Copy kth dimension into dimbuf2 if rank > 2 */
			/* ------------------------------------------- */
			memcpy(dimbuf2, ptr1[k], slen1[k]);
			dimbuf2[slen1[k]] = 0;
		    }

		    /*
		     * If first dimension and merged field then generate
		     * dimension name consisting of "MRGDIM:" + swathname +
		     * dimension size
		     */
		    if (k == 0 && cmbfldcnt > 0)
		    {
			snprintf(dimbuf2, sizeof(dimbuf2), "%s%s_%ld", "MRGDIM:",
				swathname, (long)dims[0]);
		    }
		    else
		    {
			/* Otherwise concatenate swathname to dim name */
			/* ------------------------------------------- */
			strcat(dimbuf2, ":");
			strcat(dimbuf2, swathname);
		    }

		    /* Register dimensions using "SDsetdimname" */
		    /* ---------------------------------------- */
		    SDsetdimname(SDgetdimid(sdid, k), (char *) dimbuf2);
		}



		/* Write Fill Value */
		/* ---------------- */
		for (k = 0; k < nflds0; k++)
		{
		    /* Check if fill values has been set */
		    /* --------------------------------- */
		    memcpy(utlbuf, nameptr0[k], namelen0[k]);
		    utlbuf[namelen[k]] = 0;
		    statusFill = SWgetfillvalue(swathID, utlbuf, fillval);

		    if (statusFill == 0)
		    {
			/*
			 * If merged field then fill value must be stored
			 * manually using EHfillfld
			 */
			if (cmbfldcnt > 0)
			{
			    dims[0] = indvdims[k];
			    truerank = (dims[0] == 1) ? 2 : 3;
			    EHfillfld(sdid, rank, truerank,
				      DFKNTsize(match[4]), offset[k],
				      dims, fillval);
			}
			/*
			 * If single field then just use the HDF set fill
			 * function
			 */
			else
			{
			    status = SDsetfillvalue(sdid, fillval);
			}
		    }
		}


		/*
		 * Insert SDS within the appropriate Vgroup (geo or data) and
		 * "detach" newly-created SDS
		 */
		vgid = (match[0] < 0)
		    ? SWXSwath[sID].VIDTable[0]
		    : SWXSwath[sID].VIDTable[1];

		Vaddtagref(vgid, DFTAG_NDG, SDidtoref(sdid));
		SDendaccess(sdid);

		free(nambuf);
		free(utlbuf);
	    }
	}



	/* "Contract" 1dcomb array */
	/* ----------------------- */
	i = 0;
	while (SWX1dcomb[3 * i] != 0)
	{
	    if (SWX1dcomb[3 * i + 1] == SWXSwath[sID].IDTable)
	    {
		memcpy(&SWX1dcomb[3 * i],
		       &SWX1dcomb[3 * (i + 1)],
		       (512 - i - 1) * 3 * 4);
	    }
	    else
		i++;
	}


	/* "Contract" SDcomb array */
	/* ----------------------- */
	for (i = 0; i < nflds; i++)
	{
	    if (SWXSDcomb[5 * i + 3] == SWXSwath[sID].IDTable)
	    {
		if (i == (nflds - 1))
		{
		    SWXSDcomb[5 * i] = 0;
		    *(nameptr[i] - (nflds != 1)) = 0;
		    *(dimptr[i] - (nflds != 1)) = 0;
		}
		else
		{
		    memmove(&SWXSDcomb[5 * i],
			   &SWXSDcomb[5 * (i + 1)],
			   (512 - i - 1) * 5 * 4);

		    memmove(nameptr[i],
			   nameptr[i + 1],
			   nameptr[0] + 2048 - nameptr[i + 1] - 1);

		    memmove(dimptr[i],
			   dimptr[i + 1],
			   dimptr[0] + 2048 * 2 - dimptr[i + 1] - 1);
		}

		i--;
		nflds = EHparsestr(SWXSDname, ',', nameptr, namelen);
		nflds = EHparsestr(SWXSDdims, ';', dimptr, dimlen);
	    }
	}


	/* Replace trailing delimiters on SWXSDname & SWXSDdims */
	/* ---------------------------------------------------- */
	if (nflds != 0)
	{
	    strcat(SWXSDname, ",");
	    strcat(SWXSDdims, ";");
	}



	/* Free up a bunch of dynamically allocated arrays */
	/* ----------------------------------------------- */
	free(nameptr);
	free(namelen);
	free(nameptr0);
	free(namelen0);
	free(dimptr);
	free(dimlen);
	free(offset);
	free(indvdims);




	/* "Detach" from previously attached SDSs */
	/* -------------------------------------- */
	for (k = 0; k < SWXSwath[sID].nSDS; k++)
	{
	    SDendaccess(SWXSwath[sID].sdsID[k]);
	}
	free(SWXSwath[sID].sdsID);
	SWXSwath[sID].sdsID = 0;
	SWXSwath[sID].nSDS = 0;


	/* Detach Swath Vgroups */
	/* -------------------- */
	Vdetach(SWXSwath[sID].VIDTable[0]);
	Vdetach(SWXSwath[sID].VIDTable[1]);
	Vdetach(SWXSwath[sID].VIDTable[2]);
	Vdetach(SWXSwath[sID].IDTable);


	/* Delete entries from External Arrays */
	/* ----------------------------------- */
	SWXSwath[sID].active = 0;
	SWXSwath[sID].VIDTable[0] = 0;
	SWXSwath[sID].VIDTable[1] = 0;
	SWXSwath[sID].VIDTable[2] = 0;
	SWXSwath[sID].IDTable = 0;
	SWXSwath[sID].fid = 0;


	/* Free Region Pointers */
	/* -------------------- */
	for (k = 0; k < NSWATHREGN; k++)
	{
	    if (SWXRegion[k] != 0 &&
		SWXRegion[k]->swathID == swathID)
	    {
		for (i = 0; i < 8; i++)
		{
		    if (SWXRegion[k]->DimNamePtr[i] != 0)
		    {
			free(SWXRegion[k]->DimNamePtr[i]);
		    }
		}

		free(SWXRegion[k]);
		SWXRegion[k] = 0;
	    }
	}

    }
    return (status);
}

/*----------------------------------------------------------------------------|
|  BEGIN_PROLOG                                                               |
|                                                                             |
|  FUNCTION: SWclose                                                          |
|                                                                             |
|  DESCRIPTION: Closes HDF-EOS file                                           |
|                                                                             |
|                                                                             |
|  Return Value    Type     Units     Description                             |
|  ============   ======  =========   =====================================   |
|  status         intn                return status (0) SUCCEED, (-1) FAIL    |
|                                                                             |
|  INPUTS:                                                                    |
|  fid            int32               File ID                                 |
|                                                                             |
|  OUTPUTS:                                                                   |
|             None                                                            |
|                                                                             |
|  NOTES:                                                                     |
|                                                                             |
|                                                                             |
|   Date     Programmer   Description                                         |
|  ======   ============  =================================================   |
|  Jun 96   Joel Gales    Original Programmer                                 |
|                                                                             |
|  END_PROLOG                                                                 |
-----------------------------------------------------------------------------*/
intn
SWclose(int32 fid)

{
    intn            status = 0;	/* routine return status variable */

    /* Call EHclose to perform file close */
    /* ---------------------------------- */
    status = EHclose(fid);

    return (status);
}

/*----------------------------------------------------------------------------|
|  BEGIN_PROLOG                                                               |
|                                                                             |
|  FUNCTION: SWupdatescene                                                    |
|                                                                             |
|  DESCRIPTION: Updates the StartRegion and StopRegion values                 |
|               for a specified region.                                       |
|                                                                             |
|                                                                             |
|  Return Value    Type     Units     Description                             |
|  ============   ======  =========   =====================================   |
|  status         intn                return status (0) SUCCEED, (-1) FAIL    |
|                                                                             |
|  INPUTS:                                                                    |
|  swathID        int32               Swath structure ID                      |
|  regionID       int32               Region ID                               |
|                                                                             |
|  NOTES:                                                                     |
|                                                                             |
|   Date     Programmer   Description                                         |
|  ======   ============  =================================================   |
|  Nov 98   Xinmin Hua    Original developing                                 |
|  Aug 99   Abe Taaheri   Added code to exclude regions that have the same    |
|                         start and stop.                                     |
|                                                                             |
|  END_PROLOG                                                                 |
-----------------------------------------------------------------------------*/
intn
SWupdatescene(int32 swathID, int32 regionID)
{
    intn            k;          /* Loop index */
    int32           status;     /* routine return status variable */
 
    int32           fid;        /* HDF-EOS file ID */
    int32           sdInterfaceID;      /* HDF SDS interface ID */
    int32           swVgrpID;   /* Swath Vgroup ID */
 
    int32           startReg;   /* Indexed start region */
    int32           stopReg;    /* Indexed stop region */
    int32           l_index[MAXNREGIONS]; /* to store indices when stop and 
					   start are different */
					   
    int32           ind;        /* l_index */
    int32           tempnRegions; /* temp number of regions */

    memset(l_index, 0, sizeof(int32) * MAXNREGIONS);

    /* Check for valid swath ID */
    /* ------------------------ */
    status = SWchkswid(swathID, "SWupdatescene", &fid, &sdInterfaceID,
                       &swVgrpID);
 
 
    /* Check for valid region ID */
    /* ------------------------- */
    if (status == 0)
    {
        if (regionID < 0 || regionID >= NSWATHREGN)
        {
            status = -1;
            HEpush(DFE_RANGE, "SWupdatescene", __FILE__, __LINE__);
            HEreport("Invalid Region id: %d.\n", regionID);
        }
    }
 
    /* Check for active region ID */
    /* -------------------------- */
    if (status == 0)
    {
        if (SWXRegion[regionID] == 0)
        {
            status = -1;
            HEpush(DFE_GENAPP, "SWupdatescene", __FILE__, __LINE__);
            HEreport("Inactive Region ID: %d.\n", regionID);
        }
    }
  
    if (status == 0)
    {
	tempnRegions = SWXRegion[regionID]->nRegions;
	ind =0;
	
	for (k = 0; k < SWXRegion[regionID]->nRegions; k++)
        {
           startReg = SWXRegion[regionID]->StartRegion[k];
           stopReg = SWXRegion[regionID]->StopRegion[k];
	   if(startReg == stopReg)
	   {
	       /* reduce number of regions by 1, if tempnRegions is 0 issue
		  error and break from loop*/
	       tempnRegions -= 1;
	       
	       if(tempnRegions == 0)
	       {
		   /* first free allocated memory for SWXRegion[regionID] 
		      in the function SWdefboxregion and make regionID
		      inactive */
		   free(SWXRegion[regionID]);
		   SWXRegion[regionID] = 0;
		   status = -1;
		   HEpush(DFE_GENAPP, "SWupdatescene", __FILE__, __LINE__);
		   HEreport("Inactive Region ID: %d.\n", regionID);
		   break;
	       }
	   }
	   else
	   {
	       /* store l_index number of regions that have different start and
		  stop */
	       l_index[ind] = k;
	       ind += 1;
	   }
	}
	if (status != 0)
	{
	    return (status);
	}
	else
	{
	    SWXRegion[regionID]->nRegions = tempnRegions;
	}
	/* keep starts and stops that are different in the structure  */   
	for (k = 0; k < SWXRegion[regionID]->nRegions; k++)
	{
	    SWXRegion[regionID]->StartRegion[k] =
	      SWXRegion[regionID]->StartRegion[l_index[k]];
	    SWXRegion[regionID]->StopRegion[k] =
	      SWXRegion[regionID]->StopRegion[l_index[k]];
	}
	
    }

    
    if (status == 0)
    {
 
        for (k = 0; k < SWXRegion[regionID]->nRegions; k++)
        {
 
           startReg = SWXRegion[regionID]->StartRegion[k];
           stopReg = SWXRegion[regionID]->StopRegion[k];
 
           if(startReg % 2 == 1) {
 
              SWXRegion[regionID]->StartRegion[k] = ++startReg;
 
           }
           if(stopReg % 2 == 0) {
 
              SWXRegion[regionID]->StopRegion[k] = --stopReg;
 
           }
 
        }
 
    }
    
    return(status);
 
}

/*----------------------------------------------------------------------------|
|  BEGIN_PROLOG                                                               |
|                                                                             |
|  FUNCTION: SWupdateidxmap                                                   |
|                                                                             |
|  DESCRIPTION: Updates the map l_index for a specified region.                 |
|                                                                             |
|                                                                             |
|  Return Value    Type     Units     Description                             |
|  ============   ======  =========   =====================================   |
|  nout           int32               return Number of elements in output     |
|                                     l_index array if SUCCEED, (-1) FAIL       |
|                                                                             |
|  INPUTS:                                                                    |
|  swathID        int32               Swath structure ID                      |
|  regionID       int32               Region ID                               |
|  l_indexin        int32               array of l_index values                   |
|                                                                             |
|  OUTPUTS:                                                                   |
|  l_indexout       int32               array of l_index values                   |
|  indices	  int32		      array of start and stop in region       |
|                                                                             |
|  NOTES:                                                                     |
|                                                                             |
|                                                                             |
|   Date     Programmer   Description                                         |
|  ======   ============  =================================================   |
|  Aug 97   Abe Taaheri   Original Programmer                                 |
|  AUG 97   Abe Taaheri   Add support for l_index mapping                       |
|  Sep 99   DaW		  Add support for Floating Scene Subsetting Landsat 7 |
|                                                                             |
|  END_PROLOG                                                                 |
-----------------------------------------------------------------------------*/
int32
SWupdateidxmap(int32 swathID, int32 regionID, int32 l_indexin[], int32 l_indexout[], int32 indicies[])
{
    intn            i;          /* Loop index */
    intn            j;          /* Loop index */
    intn            k;          /* Loop index */
    int32           status;     /* routine return status variable */
    int32           land_status = 3;     /* routine return status variable */
 
    int32           fid;        /* HDF-EOS file ID */
    int32           sdInterfaceID;      /* HDF SDS interface ID */
    int32           swVgrpID;   /* Swath Vgroup ID */

    int32           numtype = 0; /* Used for L7 float scene sub. */
    int32           count = 0;   /* Used for L7 float scene sub. */
 
    int32           startReg = 0;   /* Indexed start region */
    int32           stopReg = 0;    /* Indexed stop region */
    int32           nout=-1;       /* Number of elements in output l_index array */
    int32	    indexoffset = 0;
    uint8	    scene_cnt = 0;	/* Used for L7 float scene sub.      */
    uint8           detect_cnt = 0;     /* Used to convert scan to scanline  */
    intn	    gtflag = 0;
    intn	    ngtflag = 0;
    int32           *buffer1 = (int32 *)NULL;
    int32           *buffer2 = (int32 *)NULL;
 
    /* Check for valid swath ID */
    /* ------------------------ */
    status = SWchkswid(swathID, "SWupdateidxmap", &fid, &sdInterfaceID,
                       &swVgrpID);
 
 
    /* Check for valid region ID */
    /* ------------------------- */
    if (status == 0)
    {
        if (regionID < 0 || regionID >= NSWATHREGN)
        {
            status = -1;
            HEpush(DFE_RANGE, "SWupdateidxmap", __FILE__, __LINE__);
            HEreport("Invalid Region id: %d.\n", regionID);
        }
    }
 
    /* Check for active region ID */
    /* -------------------------- */
    if (status == 0)
    {
        if (SWXRegion[regionID] == 0)
        {
            status = -1;
            HEpush(DFE_GENAPP, "SWextractregion", __FILE__, __LINE__);
            HEreport("Inactive Region ID: %d.\n", regionID);
        }
    }
 
    if (status == 0)
    {
	/* Loop through all regions */
	/* ------------------------ */
	for (k = 0; k < SWXRegion[regionID]->nRegions; k++)
	{
	    
	    /* fix overlap l_index mapping problem for Landsat 7 */
	    
	    startReg = SWXRegion[regionID]->StartRegion[k];
	    stopReg = SWXRegion[regionID]->StopRegion[k];
	    
	    
            if(SWXRegion[regionID]->scanflag == 1)
            {
               indicies[0] = -1;
               indicies[1] = -1;
               j = 0;
            /* This code checks for the attribute detector_count */
            /* which is found in Landsat 7 files.  It is used    */
            /* for some of the loops.                            */
            /* ================================================= */
               land_status = SWattrinfo(swathID, "scene_count", &numtype, &count);
               if (land_status == 0)
               {
                  land_status = SWreadattr(swathID, "scene_count", &scene_cnt);
                  land_status = SWreadattr(swathID, "detector_count", &detect_cnt);
               }

	      
	      /* calculate the offsets first */
	      buffer1 = (int32 *)calloc(74, sizeof(int32));
	      buffer2 = (int32 *)calloc(74, sizeof(int32));
	      
	      status = SWidxmapinfo(swathID,"GeoTrack",
				    "ScanLineTrack", (int32*)buffer1);
	      status = SWidxmapinfo(swathID,"UpperTrack",
				    "ScanLineTrack", (int32*)buffer2);
	      
	      indexoffset = buffer2[0] - buffer1[0];
	      free(buffer1);
	      free(buffer2);

               if(SWXRegion[regionID]->band8flag == -1)
               {
                  for(i=0; i<scene_cnt;i++)
                  {
                     if(l_indexin[j] <= startReg && l_indexin[j+1] >= startReg)
                        if(indicies[0] == -1)
                           indicies[0] = j;
                     if(l_indexin[j] <= stopReg && l_indexin[j+1] >= stopReg)
                        indicies[1] = j + 1;
                     j = j + 2;
                     if(l_indexin[j] == 0 || l_indexin[j+1] == 0)
                        i = scene_cnt;
                  }
                  if(indicies[0] == -1)
                  {
                     if(startReg <= l_indexin[0])
                        indicies[0] = 0;
                  }
                  if(indicies[0] == -1)
                  {
                     j = 0;
                     for(i=0; i<scene_cnt; i++)
                     {
                        if(l_indexin[j] <= startReg && l_indexin[j+1] >= startReg)
                           if(indicies[0] == -1)
                              indicies[0] = j;
                        j = j + 1;
                        if(l_indexin[j] == 0 || l_indexin[j+1] == 0)
                           i = scene_cnt;
                     }
                  }
                  if(indicies[1] == -1)
                  {
                     j = 0;
                     for(i=0; i<scene_cnt; i++)
                     {
                        if(l_indexin[j] <= stopReg && l_indexin[j+1] >= stopReg)
                           if(indicies[1] == -1)
                              indicies[1] = j + 1;
                        j = j + 1;
                        if(l_indexin[j] == 0 || l_indexin[j+1] == 0)
                           i = scene_cnt;
                     }
                  }
                  if(indicies[1] == -1)
                     if(stopReg > l_indexin[scene_cnt - 1])
                        indicies[1] = scene_cnt - 1;
               }

	       /* This section of code handles exceptions in Landsat 7  */
	       /* data.  The Band 8 data - multiple files, data gaps	*/
               /* ===================================================== */
               if(SWXRegion[regionID]->band8flag == 1 ||
                  SWXRegion[regionID]->band8flag == 2 ||
                  SWXRegion[regionID]->band8flag == 3)
               {
                  j = 0;
                  for(i=0; i<scene_cnt; i++)
                  {
                     j = j + 2;
                     if(l_indexin[j] == 0 || l_indexin[j+1] == 0)
                     {
                        if(l_indexin[j] == 0)
                           gtflag = 1;
                        else
                           ngtflag = 1;
                        i = scene_cnt;
                     }
                  }
                  j = 0;
                  if(gtflag == 1)
                  {
                     for(i=0; i<scene_cnt; i++)
                     {
		      if( startReg >= (l_indexin[j] + indexoffset - detect_cnt) && 
			  startReg <= (l_indexin[j+1] + indexoffset - detect_cnt) )
                           if(indicies[0] == -1)
                              indicies[0] = j;
		      if( stopReg >= (l_indexin[j] + indexoffset - detect_cnt ) && 
			  stopReg <= (l_indexin[j+1] + indexoffset - detect_cnt ) )
                           indicies[1] = j + 1;
                        j = j + 2;
                        if(l_indexin[j] == 0 || l_indexin[j+1] == 0)
                           i = scene_cnt;
                     }
                     if(SWXRegion[regionID]->band8flag == 1)
                     {
                        if(indicies[1] == -1)
                           if(stopReg > (l_indexin[j - 1] + indexoffset - detect_cnt))
                              indicies[1] = j - 1;
                     }
                     if(SWXRegion[regionID]->band8flag == 2 ||
                        SWXRegion[regionID]->band8flag == 3)
                     {
		       
                        if(startReg >= (l_indexin[j - 1] + indexoffset - detect_cnt))
                        {
                           indicies[0] = -1;
                           indicies[1] = -1;
                           /* status = SWfieldinfo(swathID, "scan_no", &rank, dims2, &nt, dimlist);
                           buffer = (uint16 *)calloc(dims2[0], sizeof(uint16));
                           status = SWreadfield(swathID,"scan_no", NULL, NULL, NULL, buffer);
                           indexoffset = buffer[0] * detect_cnt;
                           free(buffer);
                           startReg = startReg - (indexoffset - detect_cnt);
                           stopReg = stopReg - (indexoffset - 1); */
                           j = 0;
                           for(i=0; i<scene_cnt; i++)
                           {
			     if( startReg >= (l_indexin[j] + indexoffset - detect_cnt) && 
				 startReg <= (l_indexin[j+1] + indexoffset - detect_cnt) )
			       if(indicies[0] == -1)
				 indicies[0] = j;
			     if( stopReg >= (l_indexin[j] + indexoffset - detect_cnt ) && 
				 stopReg <= (l_indexin[j+1] + indexoffset - detect_cnt ) )
			       indicies[1] = j + 1;
                              j = j + 2;
                              if(l_indexin[j] == 0 || l_indexin[j+1] == 0)
                                 i = scene_cnt;
                           }
                        }

                        if(indicies[0] == -1)
                        {
                           j = 0;
                           for(i=0; i<scene_cnt; i++)
                           {
			     if( startReg >= (l_indexin[j] + indexoffset - detect_cnt) && 
				 startReg <= (l_indexin[j+1] + indexoffset - detect_cnt) )
			       if(indicies[0] == -1)
				 indicies[0] = j;
		      
			     j = j + 2;
			     if(l_indexin[j] == 0 || l_indexin[j+1] == 0)
			       i = scene_cnt;
                           }
                        }
                        if(indicies[1] == -1)
                           if(stopReg > (l_indexin[j - 1] + indexoffset - detect_cnt) )
                              indicies[1] = j - 1;
                     }
                     if(indicies[1] == -1)
                     {
                        j = 0;
                        for(i=0; i<scene_cnt; i++)
                        {
			  if( stopReg >= (l_indexin[j] + indexoffset - detect_cnt ) && 
			      stopReg <= (l_indexin[j+1] + indexoffset - detect_cnt ) )
			    indicies[1] = j;
			  j = j + 2;
			  if(l_indexin[j] == 0 || l_indexin[j+1] == 0)
			    i = scene_cnt;
                        }
                     }
                  }

                  if(ngtflag == 1)
                  {
                     for(i=0; i<scene_cnt; i++)
                     {
		      if( startReg >= l_indexin[j] && startReg <= l_indexin[j+1])
                           if(indicies[0] == -1)
                              indicies[0] = j;
		      if( stopReg >= l_indexin[j] && stopReg <= l_indexin[j+1])
                           indicies[1] = j + 1;
                        j = j + 2;
                        if(l_indexin[j] == 0 || l_indexin[j+1] == 0)
                           i = scene_cnt;
                     }
                     if(SWXRegion[regionID]->band8flag == 2)
                     {
                        if(startReg >= l_indexin[j] )
                        {
                           if(indicies[0] == -1)
                              indicies[0] = j;
                           if(indicies[1] == -1)
                              indicies[1] = j;
                        }
                        if(indicies[0] == -1)
                           if(startReg <= l_indexin[0])
                              indicies[0] = 0;
                        if(indicies[1] == -1)
                           if(stopReg > l_indexin[j])
                              indicies[1] = j;
                     }
                     if(indicies[0] == -1)
                     {
                        j = 0;
                        for(i=0; i<scene_cnt; i++)
                        {
			  if( startReg >= l_indexin[j] && startReg <= l_indexin[j+1])
			    indicies[0] = j;
                           j = j + 2;
                           if(l_indexin[j] == 0 || l_indexin[j+1] == 0)
                              i = scene_cnt;
                        }
                     }
                     if(indicies[1] == -1)
                     {
                        j = 0;
                        for(i=0; i<scene_cnt; i++)
                        {
		      if( stopReg >= l_indexin[j] && stopReg <= l_indexin[j+1])
                              indicies[1] = j;
                           j = j + 2;
                           if(l_indexin[j] == 0 || l_indexin[j+1] == 0)
                              i = scene_cnt;
                        }
                     }
                     if(indicies[1] == -1)
                     {
                        if(stopReg > l_indexin[j])
                           indicies[1] = j;
                     }
                  }
                  if(indicies[0] == -1)
                  {
                     if(startReg <= (l_indexin[0]+ indexoffset - detect_cnt) )
                        indicies[0] = 0;
                     if(indicies[1] == -1)
                        if(stopReg > (l_indexin[j] + indexoffset - detect_cnt))
                           indicies[1] = j;
                  }
               }
               if (indicies[1] == -1)
               {
                  if(SWXRegion[regionID]->band8flag == 2 ||
                     SWXRegion[regionID]->band8flag == 3)
                  {
                     if(stopReg < (l_indexin[0] + indexoffset - detect_cnt))
                     {
		       /*status = SWfieldinfo(swathID, "scan_no", &rank, dims2, &nt, dimlist);
                        buffer = (uint16 *)calloc(dims2[0], sizeof(uint16));
                        status = SWreadfield(swathID,"scan_no", NULL, NULL, NULL, buffer);
                        indexoffset = buffer[0] * detect_cnt;
                        free(buffer);
                        startReg = startReg + (indexoffset - detect_cnt);
                        stopReg = stopReg + (indexoffset - 1); */
                        if(stopReg >= (l_indexin[scene_cnt - 1] + indexoffset - detect_cnt))
                        {
                           indicies[1] = scene_cnt - 1;
                        }
                        else
                        {
                           j = 0;
                           for(i=0;i<scene_cnt;i++)
                           {
		      if( stopReg >= (l_indexin[j] + indexoffset - detect_cnt ) && 
			  stopReg <= (l_indexin[j+1] + indexoffset - detect_cnt ) )
			         indicies[1] = j;
			      j = j + 2;
                              if(l_indexin[j] == 0 || l_indexin[j+1] == 0)
                                 i = scene_cnt;
                           }
                        }	
                     }

                     if(startReg > (l_indexin[j - 1] + indexoffset - detect_cnt ))
                     {
                        indicies[0] = -1;
                        indicies[1] = -1;
                        /*status = SWfieldinfo(swathID, "scan_no", &rank, dims2, &nt, dimlist);
                        buffer = (uint16 *)calloc(dims2[0], sizeof(uint16));
                        status = SWreadfield(swathID,"scan_no", NULL, NULL, NULL, buffer);
                        indexoffset = buffer[0] * detect_cnt;
                        free(buffer);
                        startReg = startReg - (indexoffset - detect_cnt);
                        stopReg = stopReg - (indexoffset - 1);*/
                        j = 0;
                        for(i=0; i<scene_cnt; i++)
                        {
		      if( startReg >= (l_indexin[j] + indexoffset - detect_cnt) && 
			  startReg <= (l_indexin[j+1] + indexoffset - detect_cnt) )
                              if(indicies[0] == -1)
                                 indicies[0] = j;
		      if( stopReg >= (l_indexin[j] + indexoffset - detect_cnt ) && 
			  stopReg <= (l_indexin[j+1] + indexoffset - detect_cnt ) )
                              indicies[1] = j + 1;
                           j = j + 2;
                           if(l_indexin[j] == 0 || l_indexin[j+1] == 0)
                              i = scene_cnt;
                        }
                        if(indicies[0] == -1)
                           if(startReg < (l_indexin[0] +  indexoffset - detect_cnt))
                              indicies[0] = 0;
                        if(indicies[1] == -1)
                           if(stopReg > (l_indexin[j - 1] + indexoffset - detect_cnt))
                              indicies[1] = j - 1;
                     }
                  }
               }
            }		/* end of if for floating scene update */
            else
            {
	       /* If start of region is odd then increment */
	       /* ---------------------------------------- */
	       if (startReg % 2 == 1)
	       {
		  startReg++;
	       }
	    
	       /* If end of region is even then decrement */
	       /* --------------------------------------- */
	       if (stopReg % 2 == 0)
	       {
		  stopReg--;
	       }

               indicies[0]=startReg;
               indicies[1]=stopReg;
	   }
        }
	
	if (l_indexout != NULL)
	{ 
           if(SWXRegion[regionID]->scanflag == 1)
           {
              nout = (indicies[1] - indicies[0] + 1);
              j = 0;
              if (nout == 1)
                 l_indexout[0] = l_indexin[indicies[0]];
              for(i=0; i<nout;i++)
              {
                 l_indexout[i] = l_indexin[indicies[0] + i];
              }
           }
           else
           {
	      /* get new l_index values */
              /* ==================== */
	      for(i = startReg; i <= stopReg  ; i++)
	      {
	         l_indexout[i-startReg] = l_indexin[i];
	      }
	      nout = (stopReg - startReg) + 1;
           }
        }
        else
        {
           nout = indicies[1] - indicies[0] + 1;
	}
     }
   
    
    if(status == -1)
    {  
	return(status);
    }
    else
    {
        return(nout);
    }
    
}



/*----------------------------------------------------------------------------|
|  BEGIN_PROLOG                                                               |
|                                                                             |
|  FUNCTION: SWgeomapinfo                                                     |
|                                                                             |
|  DESCRIPTION: Returns mapping information for dimension                     |
|                                                                             |
|                                                                             |
|  Return Value    Type     Units     Description                             |
|  ============   ======  =========   =====================================   |
|  status         intn                2 for l_indexed mapping, 1 for regular    |
|                                     mapping, 0 if the dimension is not      |
|                                     and (-1) FAIL                           |
|                                                                             |
|  INPUTS:                                                                    |
|  swathID        int32               swath structure id                      |
|  geodim         char                geolocation dimension name              |
|                                                                             |
|  OUTPUTS:                                                                   |
|                                                                             |
|  NONE                                                                       |
|                                                                             |
|  NOTES:                                                                     |
|                                                                             |
|                                                                             |
|   Date     Programmer   Description                                         |
|  ======   ============  =================================================   |
|  Aug 97   Abe Taaheri   Original Programmer                                 |
|  Sept 97  DaW           Modified return value so errors can be trapped      |
|                                                                             |
|  END_PROLOG                                                                 |
-----------------------------------------------------------------------------*/
intn
SWgeomapinfo(int32 swathID, const char *geodim)

{
    intn            status;	/* routine return status variable */
    
    int32           fid;	/* HDF-EOS file ID */
    int32           sdInterfaceID;	/* HDF SDS interface ID */
    int32           swVgrpID;	/* Swath root Vgroup ID */
    int32           idOffset = SWIDOFFSET;	/* Swath ID offset */

    char           *metabufr;	/* Pointer to structural metadata (SM) */
    char           *metabufi;	/* Pointer to structural metadata (SM) */
    char           *metaptrsr[2];/* Pointers to begin and end of SM section */
    char           *metaptrsi[2];/* Pointers to begin and end of SM section */
    char            swathname[80];	/* Swath Name */
    char           *utlstrr;	 /* Utility string */
    char           *utlstri;	 /* Utility string */
   
    
    /* Allocate space for utility string */
    /* --------------------------------- */
    utlstrr = (char *) calloc(UTLSTR_MAX_SIZE, sizeof(char));
    if(utlstrr == NULL)
    { 
	HEpush(DFE_NOSPACE,"SWgeomapinfo", __FILE__, __LINE__);
	return(-1);
    }
    utlstri = (char *) calloc(UTLSTR_MAX_SIZE, sizeof(char));
    if(utlstri == NULL)
    { 
	HEpush(DFE_NOSPACE,"SWgeomapinfo", __FILE__, __LINE__);
	free(utlstrr);
	return(-1);
    }
    status = -1;

    /* Check for valid swath id */
    status = SWchkswid(swathID, "SWgeomapinfo", &fid, &sdInterfaceID, &swVgrpID);
    if (status == 0)
    {
	/* Get swath name */
	Vgetname(SWXSwath[swathID % idOffset].IDTable, swathname);

	/* Get pointers to "DimensionMap" section within SM */
	metabufr = EHmetagroup(sdInterfaceID, swathname, "s",
				       "DimensionMap", metaptrsr);

	if(metabufr == NULL)
	{
	    free(utlstrr);
	    free(utlstri);
	    return(-1);
	}
	/* Search for mapping - GeoDim/DataDim (surrounded by quotes) */
	snprintf(utlstrr, UTLSTR_MAX_SIZE, "%s%s%s", "\t\t\t\tGeoDimension=\"", geodim,
		"\"\n\t\t\t\tDataDimension=");
	metaptrsr[0] = strstr(metaptrsr[0], utlstrr);
	
	/* Get pointers to "IndexDimensionMap" section within SM */
	metabufi = EHmetagroup(sdInterfaceID, swathname, "s",
				       "IndexDimensionMap", metaptrsi);
	if(metabufi == NULL)
	{
	    free(utlstrr);
	    free(utlstri);
	    return(-1);
	}
	/* Search for mapping - GeoDim/DataDim (surrounded by quotes) */
	snprintf(utlstri, UTLSTR_MAX_SIZE, "%s%s%s", "\t\t\t\tGeoDimension=\"", geodim,
		"\"\n\t\t\t\tDataDimension=");
	metaptrsi[0] = strstr(metaptrsi[0], utlstri);

	/*
	** If regular mapping found add 1 to status
        ** If l_indexed mapping found add 2
        */
	if (metaptrsr[0] < metaptrsr[1] && metaptrsr[0] != NULL)
	{
	    status = status + 1;	    
        }

        if (metaptrsi[0] < metaptrsi[1] && metaptrsi[0] != NULL)
        {
           status = status + 2;	    
        }

	free(metabufr);
	free(metabufi);
    }

    free(utlstrr);
    free(utlstri);

    return (status);
}

/*----------------------------------------------------------------------------|
|  BEGIN_PROLOG                                                               |
|                                                                             |
|  FUNCTION: SWsdid                                                           |
|                                                                             |
|  DESCRIPTION: Returns SD element ID for swath field                         |
|                                                                             |
|                                                                             |
|  Return Value    Type     Units     Description                             |
|  ============   ======  =========   =====================================   |
|  status         intn                return status (0) SUCCEED, (-1) FAIL    |
|                                                                             |
|  INPUTS:                                                                    |
|  swathID        int32               swath structure ID                      |
|  fieldname      const char          field name                              |
|                                                                             |
|                                                                             |
|  OUTPUTS:                                                                   |
|  sdid           int32               SD element ID                           |
|                                                                             |
|  NOTES:                                                                     |
|                                                                             |
|                                                                             |
|   Date     Programmer   Description                                         |
|  ======   ============  =================================================   |
|  Oct 07   Andrey Kiselev  Original Programmer                               |
|                                                                             |
|  END_PROLOG                                                                 |
-----------------------------------------------------------------------------*/
intn
SWsdid(int32 swathID, const char *fieldname, int32 *sdid)
{
    intn            status;	        /* routine return status variable */
    int32           fid;	        /* HDF-EOS file ID */
    int32           sdInterfaceID;      /* HDF SDS interface ID */
    int32           dum;	        /* Dummy variable */
    int32           dims[H4_MAX_VAR_DIMS]; /* Field/SDS dimensions */

    status = SWchkswid(swathID, "SWsdid", &fid, &sdInterfaceID, &dum);
    if (status != -1)
    {
        status = SWSDfldsrch(swathID, sdInterfaceID, fieldname,
                             sdid, &dum, &dum, &dum, dims, &dum);
    }

    return (status);
}
