]> granicus.if.org Git - postgis/commitdiff
Updated shapelib files from latest CVS version.
authorPaul Ramsey <pramsey@cleverelephant.ca>
Thu, 1 Nov 2001 22:57:11 +0000 (22:57 +0000)
committerPaul Ramsey <pramsey@cleverelephant.ca>
Thu, 1 Nov 2001 22:57:11 +0000 (22:57 +0000)
git-svn-id: http://svn.osgeo.org/postgis/trunk@100 b70326c6-7e19-0410-871a-916f4a2858ee

loader/dbfopen.c
loader/shapefil.h
loader/shpopen.c

index 79035065050d7a8270c321b3aee28f052607b5ef..488d0d9d76a7ff549dc9b99518f3892a3bf255dd 100644 (file)
  ******************************************************************************
  *
  * $Log$
- * Revision 1.1  2001/07/18 21:42:12  pramsey
- * Initial add of the data loader code.
+ * Revision 1.2  2001/11/01 22:57:11  pramsey
+ * Updated shapelib files from latest CVS version.
+ *
+ * Revision 1.37  2001/07/04 05:18:09  warmerda
+ * do last fix properly
+ *
+ * Revision 1.36  2001/07/04 05:16:09  warmerda
+ * fixed fieldname comparison in DBFGetFieldIndex
+ *
+ * Revision 1.35  2001/06/22 02:10:06  warmerda
+ * fixed NULL shape support with help from Jim Matthews
+ *
+ * Revision 1.33  2001/05/31 19:20:13  warmerda
+ * added DBFGetFieldIndex()
+ *
+ * Revision 1.32  2001/05/31 18:15:40  warmerda
+ * Added support for NULL fields in DBF files
+ *
+ * Revision 1.31  2001/05/23 13:36:52  warmerda
+ * added use of SHPAPI_CALL
+ *
+ * Revision 1.30  2000/12/05 14:43:38  warmerda
+ * DBReadAttribute() white space trimming bug fix
+ *
+ * Revision 1.29  2000/10/05 14:36:44  warmerda
+ * fix bug with writing very wide numeric fields
+ *
+ * Revision 1.28  2000/09/25 14:18:07  warmerda
+ * Added some casts of strlen() return result to fix warnings on some
+ * systems, as submitted by Daniel.
+ *
+ * Revision 1.27  2000/09/25 14:15:51  warmerda
+ * added DBFGetNativeFieldType()
+ *
+ * Revision 1.26  2000/07/07 13:39:45  warmerda
+ * removed unused variables, and added system include files
+ *
+ * Revision 1.25  2000/05/29 18:19:13  warmerda
+ * avoid use of uchar, and adding casting fix
+ *
+ * Revision 1.24  2000/05/23 13:38:27  warmerda
+ * Added error checks on return results of fread() and fseek().
+ *
+ * Revision 1.23  2000/05/23 13:25:49  warmerda
+ * Avoid crashing if field or record are out of range in dbfread*attribute().
  *
  * Revision 1.22  1999/12/15 13:47:24  warmerda
  * Added stdlib.h to ensure that atof() is prototyped.
@@ -116,8 +159,8 @@ static char rcsid[] =
 
 #include <math.h>
 #include <stdlib.h>
-
-typedef unsigned char uchar;
+#include <ctype.h>
+#include <string.h>
 
 #ifndef FALSE
 #  define FALSE                0
@@ -155,7 +198,7 @@ static void * SfRealloc( void * pMem, int nNewSize )
 static void DBFWriteHeader(DBFHandle psDBF)
 
 {
-    uchar      abyHeader[XBASE_FLDHDR_SZ];
+    unsigned char      abyHeader[XBASE_FLDHDR_SZ];
     int                i;
 
     if( !psDBF->bNoHeader )
@@ -228,11 +271,12 @@ static void DBFFlushRecord( DBFHandle psDBF )
 /*      Open a .dbf file.                                               */
 /************************************************************************/
    
-DBFHandle DBFOpen( const char * pszFilename, const char * pszAccess )
+DBFHandle SHPAPI_CALL
+DBFOpen( const char * pszFilename, const char * pszAccess )
 
 {
     DBFHandle          psDBF;
-    uchar              *pabyBuf;
+    unsigned char              *pabyBuf;
     int                        nFields, nRecords, nHeadLen, nRecLen, iField, i;
     char               *pszBasename, *pszFullname;
 
@@ -244,6 +288,12 @@ DBFHandle DBFOpen( const char * pszFilename, const char * pszAccess )
         && strcmp(pszAccess,"r+b") != 0 )
         return( NULL );
 
+    if( strcmp(pszAccess,"r") == 0 )
+        pszAccess = "rb";
+    if( strcmp(pszAccess,"r+") == 0 )
+        pszAccess = "rb+";
+
 /* -------------------------------------------------------------------- */
 /*     Compute the base (layer) name.  If there is any extension       */
 /*     on the passed in filename we will strip it off.                 */
@@ -286,7 +336,7 @@ DBFHandle DBFOpen( const char * pszFilename, const char * pszAccess )
 /* -------------------------------------------------------------------- */
 /*  Read Table Header info                                              */
 /* -------------------------------------------------------------------- */
-    pabyBuf = (uchar *) malloc(500);
+    pabyBuf = (unsigned char *) malloc(500);
     fread( pabyBuf, 32, 1, psDBF->fp );
 
     psDBF->nRecords = nRecords = 
@@ -303,7 +353,7 @@ DBFHandle DBFOpen( const char * pszFilename, const char * pszAccess )
 /*  Read in Field Definitions                                           */
 /* -------------------------------------------------------------------- */
     
-    pabyBuf = (uchar *) SfRealloc(pabyBuf,nHeadLen);
+    pabyBuf = (unsigned char *) SfRealloc(pabyBuf,nHeadLen);
     psDBF->pszHeader = (char *) pabyBuf;
 
     fseek( psDBF->fp, 32, 0 );
@@ -316,7 +366,7 @@ DBFHandle DBFOpen( const char * pszFilename, const char * pszAccess )
 
     for( iField = 0; iField < nFields; iField++ )
     {
-       uchar           *pabyFInfo;
+       unsigned char           *pabyFInfo;
 
        pabyFInfo = pabyBuf+iField*32;
 
@@ -346,7 +396,8 @@ DBFHandle DBFOpen( const char * pszFilename, const char * pszAccess )
 /*                              DBFClose()                              */
 /************************************************************************/
 
-void   DBFClose(DBFHandle psDBF)
+void SHPAPI_CALL
+DBFClose(DBFHandle psDBF)
 {
 /* -------------------------------------------------------------------- */
 /*      Write out header if not already written.                        */
@@ -362,7 +413,7 @@ void        DBFClose(DBFHandle psDBF)
 /* -------------------------------------------------------------------- */
     if( psDBF->bUpdated )
     {
-       uchar           abyFileHeader[32];
+       unsigned char           abyFileHeader[32];
 
        fseek( psDBF->fp, 0, 0 );
        fread( abyFileHeader, 32, 1, psDBF->fp );
@@ -412,7 +463,8 @@ void        DBFClose(DBFHandle psDBF)
 /*      Create a new .dbf file.                                         */
 /************************************************************************/
 
-DBFHandle DBFCreate( const char * pszFilename )
+DBFHandle SHPAPI_CALL
+DBFCreate( const char * pszFilename )
 
 {
     DBFHandle  psDBF;
@@ -487,8 +539,9 @@ DBFHandle DBFCreate( const char * pszFilename )
 /*      are written.                                                    */
 /************************************************************************/
 
-int    DBFAddField(DBFHandle psDBF, const char * pszFieldName, 
-                   DBFFieldType eType, int nWidth, int nDecimals )
+int SHPAPI_CALL
+DBFAddField(DBFHandle psDBF, const char * pszFieldName, 
+            DBFFieldType eType, int nWidth, int nDecimals )
 
 {
     char       *pszFInfo;
@@ -550,7 +603,7 @@ int DBFAddField(DBFHandle psDBF, const char * pszFieldName,
     for( i = 0; i < 32; i++ )
         pszFInfo[i] = '\0';
 
-    if( strlen(pszFieldName) < 10 )
+    if( (int) strlen(pszFieldName) < 10 )
         strncpy( pszFInfo, pszFieldName, strlen(pszFieldName));
     else
         strncpy( pszFInfo, pszFieldName, 10);
@@ -588,30 +641,48 @@ static void *DBFReadAttribute(DBFHandle psDBF, int hEntity, int iField,
 
 {
     int                nRecordOffset;
-    uchar      *pabyRec;
+    unsigned char      *pabyRec;
     void       *pReturnField = NULL;
 
     static double dDoubleField;
 
 /* -------------------------------------------------------------------- */
-/*     Have we read the record?                                        */
+/*      Verify selection.                                               */
 /* -------------------------------------------------------------------- */
     if( hEntity < 0 || hEntity >= psDBF->nRecords )
         return( NULL );
 
+    if( iField < 0 || iField >= psDBF->nFields )
+        return( NULL );
+
+/* -------------------------------------------------------------------- */
+/*     Have we read the record?                                        */
+/* -------------------------------------------------------------------- */
     if( psDBF->nCurrentRecord != hEntity )
     {
        DBFFlushRecord( psDBF );
 
        nRecordOffset = psDBF->nRecordLength * hEntity + psDBF->nHeaderLength;
 
-       fseek( psDBF->fp, nRecordOffset, 0 );
-       fread( psDBF->pszCurrentRecord, psDBF->nRecordLength, 1, psDBF->fp );
+       if( fseek( psDBF->fp, nRecordOffset, 0 ) != 0 )
+        {
+            fprintf( stderr, "fseek(%d) failed on DBF file.\n",
+                     nRecordOffset );
+            return NULL;
+        }
+
+       if( fread( psDBF->pszCurrentRecord, psDBF->nRecordLength, 
+                   1, psDBF->fp ) != 1 )
+        {
+            fprintf( stderr, "fread(%d) failed on DBF file.\n",
+                     psDBF->nRecordLength );
+            return NULL;
+        }
 
        psDBF->nCurrentRecord = hEntity;
     }
 
-    pabyRec = (uchar *) psDBF->pszCurrentRecord;
+    pabyRec = (unsigned char *) psDBF->pszCurrentRecord;
 
 /* -------------------------------------------------------------------- */
 /*     Ensure our field buffer is large enough to hold this buffer.    */
@@ -625,7 +696,8 @@ static void *DBFReadAttribute(DBFHandle psDBF, int hEntity, int iField,
 /* -------------------------------------------------------------------- */
 /*     Extract the requested field.                                    */
 /* -------------------------------------------------------------------- */
-    strncpy( pszStringField, pabyRec+psDBF->panFieldOffset[iField],
+    strncpy( pszStringField, 
+            ((const char *) pabyRec) + psDBF->panFieldOffset[iField],
             psDBF->panFieldSize[iField] );
     pszStringField[psDBF->panFieldSize[iField]] = '\0';
 
@@ -657,9 +729,8 @@ static void *DBFReadAttribute(DBFHandle psDBF, int hEntity, int iField,
             *(pchDst++) = *(pchSrc++);
         *pchDst = '\0';
 
-        while( *(--pchDst) == ' ' && pchDst != pszStringField )
+        while( pchDst != pszStringField && *(--pchDst) == ' ' )
             *pchDst = '\0';
-
     }
 #endif
     
@@ -672,14 +743,18 @@ static void *DBFReadAttribute(DBFHandle psDBF, int hEntity, int iField,
 /*      Read an integer attribute.                                      */
 /************************************************************************/
 
-int    DBFReadIntegerAttribute( DBFHandle psDBF, int iRecord, int iField )
+int SHPAPI_CALL
+DBFReadIntegerAttribute( DBFHandle psDBF, int iRecord, int iField )
 
 {
     double     *pdValue;
 
     pdValue = (double *) DBFReadAttribute( psDBF, iRecord, iField, 'N' );
 
-    return( (int) *pdValue );
+    if( pdValue == NULL )
+        return 0;
+    else
+        return( (int) *pdValue );
 }
 
 /************************************************************************/
@@ -688,14 +763,18 @@ int       DBFReadIntegerAttribute( DBFHandle psDBF, int iRecord, int iField )
 /*      Read a double attribute.                                        */
 /************************************************************************/
 
-double DBFReadDoubleAttribute( DBFHandle psDBF, int iRecord, int iField )
+double SHPAPI_CALL
+DBFReadDoubleAttribute( DBFHandle psDBF, int iRecord, int iField )
 
 {
     double     *pdValue;
 
     pdValue = (double *) DBFReadAttribute( psDBF, iRecord, iField, 'N' );
 
-    return( *pdValue );
+    if( pdValue == NULL )
+        return 0.0;
+    else
+        return( *pdValue );
 }
 
 /************************************************************************/
@@ -704,19 +783,59 @@ double    DBFReadDoubleAttribute( DBFHandle psDBF, int iRecord, int iField )
 /*      Read a string attribute.                                        */
 /************************************************************************/
 
-const char *DBFReadStringAttribute( DBFHandle psDBF, int iRecord, int iField )
+const char SHPAPI_CALL1(*)
+DBFReadStringAttribute( DBFHandle psDBF, int iRecord, int iField )
 
 {
     return( (const char *) DBFReadAttribute( psDBF, iRecord, iField, 'C' ) );
 }
 
+/************************************************************************/
+/*                         DBFIsAttributeNULL()                         */
+/*                                                                      */
+/*      Return TRUE if value for field is NULL.                         */
+/*                                                                      */
+/*      Contributed by Jim Matthews.                                    */
+/************************************************************************/
+
+int SHPAPI_CALL
+DBFIsAttributeNULL( DBFHandle psDBF, int iRecord, int iField )
+
+{
+    const char *pszValue;
+
+    pszValue = DBFReadStringAttribute( psDBF, iRecord, iField );
+
+    switch(psDBF->pachFieldType[iField])
+    {
+      case 'N':
+      case 'F':
+        /* NULL numeric fields have value "****************" */
+        return pszValue[0] == '*';
+
+      case 'D':
+        /* NULL date fields have value "00000000" */
+        return strncmp(pszValue,"00000000",8) == 0;
+
+      case 'L':
+        /* NULL boolean fields have value "?" */ 
+        return pszValue[0] == '?';
+
+      default:
+        /* empty string fields are considered NULL */
+        return strlen(pszValue) == 0;
+    }
+    return FALSE;
+}
+
 /************************************************************************/
 /*                          DBFGetFieldCount()                          */
 /*                                                                      */
 /*      Return the number of fields in this table.                      */
 /************************************************************************/
 
-int    DBFGetFieldCount( DBFHandle psDBF )
+int SHPAPI_CALL
+DBFGetFieldCount( DBFHandle psDBF )
 
 {
     return( psDBF->nFields );
@@ -728,7 +847,8 @@ int DBFGetFieldCount( DBFHandle psDBF )
 /*      Return the number of records in this table.                     */
 /************************************************************************/
 
-int    DBFGetRecordCount( DBFHandle psDBF )
+int SHPAPI_CALL
+DBFGetRecordCount( DBFHandle psDBF )
 
 {
     return( psDBF->nRecords );
@@ -740,8 +860,9 @@ int DBFGetRecordCount( DBFHandle psDBF )
 /*      Return any requested information about the field.               */
 /************************************************************************/
 
-DBFFieldType DBFGetFieldInfo( DBFHandle psDBF, int iField, char * pszFieldName,
-                             int * pnWidth, int * pnDecimals )
+DBFFieldType SHPAPI_CALL
+DBFGetFieldInfo( DBFHandle psDBF, int iField, char * pszFieldName,
+                 int * pnWidth, int * pnDecimals )
 
 {
     if( iField < 0 || iField >= psDBF->nFields )
@@ -789,8 +910,8 @@ static int DBFWriteAttribute(DBFHandle psDBF, int hEntity, int iField,
 
 {
     int                nRecordOffset, i, j;
-    uchar      *pabyRec;
-    char       szSField[40], szFormat[12];
+    unsigned char      *pabyRec;
+    char       szSField[400], szFormat[20];
 
 /* -------------------------------------------------------------------- */
 /*     Is this a valid record?                                         */
@@ -813,7 +934,6 @@ static int DBFWriteAttribute(DBFHandle psDBF, int hEntity, int iField,
            psDBF->pszCurrentRecord[i] = ' ';
 
        psDBF->nCurrentRecord = hEntity;
-       
     }
 
 /* -------------------------------------------------------------------- */
@@ -832,41 +952,90 @@ static int DBFWriteAttribute(DBFHandle psDBF, int hEntity, int iField,
        psDBF->nCurrentRecord = hEntity;
     }
 
-    pabyRec = (uchar *) psDBF->pszCurrentRecord;
+    pabyRec = (unsigned char *) psDBF->pszCurrentRecord;
+
+    psDBF->bCurrentRecordModified = TRUE;
+    psDBF->bUpdated = TRUE;
+
+/* -------------------------------------------------------------------- */
+/*      Translate NULL value to valid DBF file representation.          */
+/*                                                                      */
+/*      Contributed by Jim Matthews.                                    */
+/* -------------------------------------------------------------------- */
+    if( pValue == NULL )
+    {
+        switch(psDBF->pachFieldType[iField])
+        {
+          case 'N':
+          case 'F':
+           /* NULL numeric fields have value "****************" */
+            memset( (char *) (pabyRec+psDBF->panFieldOffset[iField]), '*', 
+                    psDBF->panFieldSize[iField] );
+            break;
+
+          case 'D':
+           /* NULL date fields have value "00000000" */
+            memset( (char *) (pabyRec+psDBF->panFieldOffset[iField]), '0', 
+                    psDBF->panFieldSize[iField] );
+            break;
+
+          case 'L':
+           /* NULL boolean fields have value "?" */ 
+            memset( (char *) (pabyRec+psDBF->panFieldOffset[iField]), '?', 
+                    psDBF->panFieldSize[iField] );
+            break;
+
+          default:
+            /* empty string fields are considered NULL */
+            memset( (char *) (pabyRec+psDBF->panFieldOffset[iField]), '\0', 
+                    psDBF->panFieldSize[iField] );
+            break;
+        }
+        return TRUE;
+    }
 
 /* -------------------------------------------------------------------- */
 /*      Assign all the record fields.                                   */
 /* -------------------------------------------------------------------- */
-       switch( psDBF->pachFieldType[iField] )
+    switch( psDBF->pachFieldType[iField] )
     {
       case 'D':
       case 'N':
       case 'F':
-  if( psDBF->panFieldDecimals[iField] == 0 )
+       if( psDBF->panFieldDecimals[iField] == 0 )
        {
-               sprintf( szFormat, "%%%dd", psDBF->panFieldSize[iField] );
+            int                nWidth = psDBF->panFieldSize[iField];
+
+            if( sizeof(szSField)-2 < nWidth )
+                nWidth = sizeof(szSField)-2;
+
+           sprintf( szFormat, "%%%dd", nWidth );
            sprintf(szSField, szFormat, (int) *((double *) pValue) );
-           if( strlen(szSField) > psDBF->panFieldSize[iField] )
+           if( (int)strlen(szSField) > psDBF->panFieldSize[iField] )
                szSField[psDBF->panFieldSize[iField]] = '\0';
+
            strncpy((char *) (pabyRec+psDBF->panFieldOffset[iField]),
                    szSField, strlen(szSField) );
        }
        else
        {
+            int                nWidth = psDBF->panFieldSize[iField];
+
+            if( sizeof(szSField)-2 < nWidth )
+                nWidth = sizeof(szSField)-2;
+
            sprintf( szFormat, "%%%d.%df", 
-                    psDBF->panFieldSize[iField],
-                    psDBF->panFieldDecimals[iField] );
+                     nWidth, psDBF->panFieldDecimals[iField] );
            sprintf(szSField, szFormat, *((double *) pValue) );
-           if( strlen(szSField) > psDBF->panFieldSize[iField] )
+           if( (int) strlen(szSField) > psDBF->panFieldSize[iField] )
                szSField[psDBF->panFieldSize[iField]] = '\0';
            strncpy((char *) (pabyRec+psDBF->panFieldOffset[iField]),
                    szSField, strlen(szSField) );
        }
-
        break;
 
       default:
-       if( strlen((char *) pValue) > psDBF->panFieldSize[iField] )
+       if( (int) strlen((char *) pValue) > psDBF->panFieldSize[iField] )
            j = psDBF->panFieldSize[iField];
        else
         {
@@ -880,9 +1049,6 @@ static int DBFWriteAttribute(DBFHandle psDBF, int hEntity, int iField,
        break;
     }
 
-    psDBF->bCurrentRecordModified = TRUE;
-    psDBF->bUpdated = TRUE;
-
     return( TRUE );
 }
 
@@ -892,8 +1058,9 @@ static int DBFWriteAttribute(DBFHandle psDBF, int hEntity, int iField,
 /*      Write a double attribute.                                       */
 /************************************************************************/
 
-int DBFWriteDoubleAttribute( DBFHandle psDBF, int iRecord, int iField,
-                            double dValue )
+int SHPAPI_CALL
+DBFWriteDoubleAttribute( DBFHandle psDBF, int iRecord, int iField,
+                         double dValue )
 
 {
     return( DBFWriteAttribute( psDBF, iRecord, iField, (void *) &dValue ) );
@@ -905,8 +1072,9 @@ int DBFWriteDoubleAttribute( DBFHandle psDBF, int iRecord, int iField,
 /*      Write a integer attribute.                                      */
 /************************************************************************/
 
-int DBFWriteIntegerAttribute( DBFHandle psDBF, int iRecord, int iField,
-                             int nValue )
+int SHPAPI_CALL
+DBFWriteIntegerAttribute( DBFHandle psDBF, int iRecord, int iField,
+                          int nValue )
 
 {
     double     dValue = nValue;
@@ -920,24 +1088,39 @@ int DBFWriteIntegerAttribute( DBFHandle psDBF, int iRecord, int iField,
 /*      Write a string attribute.                                       */
 /************************************************************************/
 
-int DBFWriteStringAttribute( DBFHandle psDBF, int iRecord, int iField,
-                            const char * pszValue )
+int SHPAPI_CALL
+DBFWriteStringAttribute( DBFHandle psDBF, int iRecord, int iField,
+                         const char * pszValue )
 
 {
     return( DBFWriteAttribute( psDBF, iRecord, iField, (void *) pszValue ) );
 }
 
+/************************************************************************/
+/*                      DBFWriteNULLAttribute()                         */
+/*                                                                      */
+/*      Write a string attribute.                                       */
+/************************************************************************/
+
+int SHPAPI_CALL
+DBFWriteNULLAttribute( DBFHandle psDBF, int iRecord, int iField )
+
+{
+    return( DBFWriteAttribute( psDBF, iRecord, iField, NULL ) );
+}
+
 /************************************************************************/
 /*                         DBFWriteTuple()                              */
 /*                                                                     */
 /*     Write an attribute record to the file.                          */
 /************************************************************************/
 
-int DBFWriteTuple(DBFHandle psDBF, int hEntity, void * pRawTuple )
+int SHPAPI_CALL
+DBFWriteTuple(DBFHandle psDBF, int hEntity, void * pRawTuple )
 
 {
     int                nRecordOffset, i;
-    uchar      *pabyRec;
+    unsigned char      *pabyRec;
 
 /* -------------------------------------------------------------------- */
 /*     Is this a valid record?                                         */
@@ -978,7 +1161,7 @@ int DBFWriteTuple(DBFHandle psDBF, int hEntity, void * pRawTuple )
        psDBF->nCurrentRecord = hEntity;
     }
 
-    pabyRec = (uchar *) psDBF->pszCurrentRecord;
+    pabyRec = (unsigned char *) psDBF->pszCurrentRecord;
 
     memcpy ( pabyRec, pRawTuple,  psDBF->nRecordLength );
 
@@ -994,11 +1177,12 @@ int DBFWriteTuple(DBFHandle psDBF, int hEntity, void * pRawTuple )
 /*      Read one of the attribute fields of a record.                   */
 /************************************************************************/
 
-const char *DBFReadTuple(DBFHandle psDBF, int hEntity )
+const char SHPAPI_CALL1(*)
+DBFReadTuple(DBFHandle psDBF, int hEntity )
 
 {
     int                nRecordOffset;
-    uchar      *pabyRec;
+    unsigned char      *pabyRec;
     static char        *pReturnTuple = NULL;
 
     static int nTupleLen = 0;
@@ -1021,7 +1205,7 @@ const char *DBFReadTuple(DBFHandle psDBF, int hEntity )
        psDBF->nCurrentRecord = hEntity;
     }
 
-    pabyRec = (uchar *) psDBF->pszCurrentRecord;
+    pabyRec = (unsigned char *) psDBF->pszCurrentRecord;
 
     if ( nTupleLen < psDBF->nRecordLength) {
       nTupleLen = psDBF->nRecordLength;
@@ -1039,7 +1223,8 @@ const char *DBFReadTuple(DBFHandle psDBF, int hEntity )
 /*      Read one of the attribute fields of a record.                   */
 /************************************************************************/
 
-DBFHandle DBFCloneEmpty(DBFHandle psDBF, const char * pszFilename ) 
+DBFHandle SHPAPI_CALL
+DBFCloneEmpty(DBFHandle psDBF, const char * pszFilename ) 
 {
     DBFHandle  newDBF;
 
@@ -1072,3 +1257,70 @@ DBFHandle DBFCloneEmpty(DBFHandle psDBF, const char * pszFilename )
 
    return ( newDBF );
 }
+
+/************************************************************************/
+/*                       DBFGetNativeFieldType()                        */
+/*                                                                      */
+/*      Return the DBase field type for the specified field.            */
+/*                                                                      */
+/*      Value can be one of: 'C' (String), 'D' (Date), 'F' (Float),     */
+/*                           'N' (Numeric, with or without decimal),    */
+/*                           'L' (Logical),                             */
+/*                           'M' (Memo: 10 digits .DBT block ptr)       */
+/************************************************************************/
+
+char SHPAPI_CALL
+DBFGetNativeFieldType( DBFHandle psDBF, int iField )
+
+{
+    if( iField >=0 && iField < psDBF->nFields )
+        return psDBF->pachFieldType[iField];
+
+    return  ' ';
+}
+
+/************************************************************************/
+/*                            str_to_upper()                            */
+/************************************************************************/
+
+static void str_to_upper (char *string)
+{
+    int len;
+    short i = -1;
+
+    len = strlen (string);
+
+    while (++i < len)
+        if (isalpha(string[i]) && islower(string[i]))
+            string[i] = toupper ((int)string[i]);
+}
+
+/************************************************************************/
+/*                          DBFGetFieldIndex()                          */
+/*                                                                      */
+/*      Get the index number for a field in a .dbf file.                */
+/*                                                                      */
+/*      Contributed by Jim Matthews.                                    */
+/************************************************************************/
+
+int SHPAPI_CALL
+DBFGetFieldIndex(DBFHandle psDBF, const char *pszFieldName)
+
+{
+    char          name[12], name1[12], name2[12];
+    int           i;
+
+    strncpy(name1, pszFieldName,11);
+    str_to_upper(name1);
+
+    for( i = 0; i < DBFGetFieldCount(psDBF); i++ )
+    {
+        DBFGetFieldInfo( psDBF, i, name, NULL, NULL );
+        strncpy(name2,name,11);
+        str_to_upper(name2);
+
+        if(!strncmp(name1,name2,10))
+            return(i);
+    }
+    return(-1);
+}
index 5b2d781a65136ddbf8a6cbf1dbd372f87f27eb0a..35a56071d8e664821147b1db168959ff0d894b6e 100644 (file)
  ******************************************************************************
  *
  * $Log$
- * Revision 1.1  2001/07/18 21:42:12  pramsey
- * Initial add of the data loader code.
+ * Revision 1.2  2001/11/01 22:57:11  pramsey
+ * Updated shapelib files from latest CVS version.
+ *
+ * Revision 1.21  2001/11/01 16:29:55  warmerda
+ * move pabyRec into SHPInfo for thread safety
+ *
+ * Revision 1.20  2001/07/20 13:06:02  warmerda
+ * fixed SHPAPI attribute for SHPTreeFindLikelyShapes
+ *
+ * Revision 1.19  2001/05/31 19:20:13  warmerda
+ * added DBFGetFieldIndex()
+ *
+ * Revision 1.18  2001/05/31 18:15:40  warmerda
+ * Added support for NULL fields in DBF files
+ *
+ * Revision 1.17  2001/05/23 13:36:52  warmerda
+ * added use of SHPAPI_CALL
+ *
+ * Revision 1.16  2000/09/25 14:15:59  warmerda
+ * added DBFGetNativeFieldType()
  *
  * Revision 1.15  2000/02/16 16:03:51  warmerda
  * added null shape support
 #ifdef __cplusplus
 extern "C" {
 #endif
+
+#ifndef SHPAPI_CALL
+#define SHPAPI_CALL
+#endif
+
+#define SHPAPI_CALL1(x)      * SHPAPI_CALL
     
 /************************************************************************/
 /*                        Configuration options.                        */
@@ -132,6 +156,9 @@ typedef     struct
     double     adBoundsMax[4];
 
     int                bUpdated;
+
+    unsigned char *pabyRec;
+    int         nBufSize;
 } SHPInfo;
 
 typedef SHPInfo * SHPHandle;
@@ -201,27 +228,39 @@ typedef struct
 /* -------------------------------------------------------------------- */
 /*      SHP API Prototypes                                              */
 /* -------------------------------------------------------------------- */
-SHPHandle SHPOpen( const char * pszShapeFile, const char * pszAccess );
-SHPHandle SHPCreate( const char * pszShapeFile, int nShapeType );
-void   SHPGetInfo( SHPHandle hSHP, int * pnEntities, int * pnShapeType,
-                    double * padfMinBound, double * padfMaxBound );
-
-SHPObject *SHPReadObject( SHPHandle hSHP, int iShape );
-int    SHPWriteObject( SHPHandle hSHP, int iShape, SHPObject * psObject );
-
-void   SHPDestroyObject( SHPObject * psObject );
-void   SHPComputeExtents( SHPObject * psObject );
-SHPObject *SHPCreateObject( int nSHPType, int nShapeId,
-                            int nParts, int * panPartStart, int * panPartType,
-                            int nVertices, double * padfX, double * padfY,
-                            double * padfZ, double * padfM );
-SHPObject *SHPCreateSimpleObject( int nSHPType, int nVertices,
-                              double * padfX, double * padfY, double * padfZ );
-
-void   SHPClose( SHPHandle hSHP );
-
-const char *SHPTypeName( int nSHPType );
-const char *SHPPartTypeName( int nPartType );
+SHPHandle SHPAPI_CALL
+      SHPOpen( const char * pszShapeFile, const char * pszAccess );
+SHPHandle SHPAPI_CALL
+      SHPCreate( const char * pszShapeFile, int nShapeType );
+void SHPAPI_CALL
+      SHPGetInfo( SHPHandle hSHP, int * pnEntities, int * pnShapeType,
+                  double * padfMinBound, double * padfMaxBound );
+
+SHPObject SHPAPI_CALL1(*)
+      SHPReadObject( SHPHandle hSHP, int iShape );
+int SHPAPI_CALL
+      SHPWriteObject( SHPHandle hSHP, int iShape, SHPObject * psObject );
+
+void SHPAPI_CALL
+      SHPDestroyObject( SHPObject * psObject );
+void SHPAPI_CALL
+      SHPComputeExtents( SHPObject * psObject );
+SHPObject SHPAPI_CALL1(*)
+      SHPCreateObject( int nSHPType, int nShapeId,
+                       int nParts, int * panPartStart, int * panPartType,
+                       int nVertices, double * padfX, double * padfY,
+                       double * padfZ, double * padfM );
+SHPObject SHPAPI_CALL1(*)
+      SHPCreateSimpleObject( int nSHPType, int nVertices,
+                             double * padfX, double * padfY, double * padfZ );
+
+void SHPAPI_CALL
+      SHPClose( SHPHandle hSHP );
+
+const char SHPAPI_CALL1(*)
+      SHPTypeName( int nSHPType );
+const char SHPAPI_CALL1(*)
+      SHPPartTypeName( int nPartType );
 
 /* -------------------------------------------------------------------- */
 /*      Shape quadtree indexing API.                                    */
@@ -257,24 +296,34 @@ typedef struct
     SHPTreeNode        *psRoot;
 } SHPTree;
 
-SHPTree *SHPCreateTree( SHPHandle hSHP, int nDimension, int nMaxDepth,
-                        double *padfBoundsMin, double *padfBoundsMax );
-void     SHPDestroyTree( SHPTree * hTree );
-
-int    SHPWriteTree( SHPTree *hTree, const char * pszFilename );
-SHPTree SHPReadTree( const char * pszFilename );
-
-int    SHPTreeAddObject( SHPTree * hTree, SHPObject * psObject );
-int    SHPTreeAddShapeId( SHPTree * hTree, SHPObject * psObject );
-int    SHPTreeRemoveShapeId( SHPTree * hTree, int nShapeId );
-
-void   SHPTreeTrimExtraNodes( SHPTree * hTree );
-
-int    *SHPTreeFindLikelyShapes( SHPTree * hTree,
-                                 double * padfBoundsMin,
-                                 double * padfBoundsMax,
-                                 int * );
-int     SHPCheckBoundsOverlap( double *, double *, double *, double *, int );
+SHPTree SHPAPI_CALL1(*)
+      SHPCreateTree( SHPHandle hSHP, int nDimension, int nMaxDepth,
+                     double *padfBoundsMin, double *padfBoundsMax );
+void    SHPAPI_CALL
+      SHPDestroyTree( SHPTree * hTree );
+
+int    SHPAPI_CALL
+      SHPWriteTree( SHPTree *hTree, const char * pszFilename );
+SHPTree SHPAPI_CALL
+      SHPReadTree( const char * pszFilename );
+
+int    SHPAPI_CALL
+      SHPTreeAddObject( SHPTree * hTree, SHPObject * psObject );
+int    SHPAPI_CALL
+      SHPTreeAddShapeId( SHPTree * hTree, SHPObject * psObject );
+int    SHPAPI_CALL
+      SHPTreeRemoveShapeId( SHPTree * hTree, int nShapeId );
+
+void   SHPAPI_CALL
+      SHPTreeTrimExtraNodes( SHPTree * hTree );
+
+int    SHPAPI_CALL1(*)
+      SHPTreeFindLikelyShapes( SHPTree * hTree,
+                               double * padfBoundsMin,
+                               double * padfBoundsMax,
+                               int * );
+int     SHPAPI_CALL
+      SHPCheckBoundsOverlap( double *, double *, double *, double *, int );
 
 /************************************************************************/
 /*                             DBF Support.                             */
@@ -309,40 +358,64 @@ typedef enum {
   FTString,
   FTInteger,
   FTDouble,
-  FTInvalid,
+  FTInvalid
 } DBFFieldType;
 
 #define XBASE_FLDHDR_SZ       32
 
-DBFHandle DBFOpen( const char * pszDBFFile, const char * pszAccess );
-DBFHandle DBFCreate( const char * pszDBFFile );
-
-int    DBFGetFieldCount( DBFHandle psDBF );
-int    DBFGetRecordCount( DBFHandle psDBF );
-int    DBFAddField( DBFHandle hDBF, const char * pszFieldName,
-                    DBFFieldType eType, int nWidth, int nDecimals );
-
-DBFFieldType DBFGetFieldInfo( DBFHandle psDBF, int iField, 
-                             char * pszFieldName, 
-                             int * pnWidth, int * pnDecimals );
-
-int    DBFReadIntegerAttribute( DBFHandle hDBF, int iShape, int iField );
-double         DBFReadDoubleAttribute( DBFHandle hDBF, int iShape, int iField );
-const char *DBFReadStringAttribute( DBFHandle hDBF, int iShape, int iField );
-
-int DBFWriteIntegerAttribute( DBFHandle hDBF, int iShape, int iField, 
-                             int nFieldValue );
-int DBFWriteDoubleAttribute( DBFHandle hDBF, int iShape, int iField,
-                            double dFieldValue );
-int DBFWriteStringAttribute( DBFHandle hDBF, int iShape, int iField,
-                            const char * pszFieldValue );
-
-const char *DBFReadTuple(DBFHandle psDBF, int hEntity );
-int DBFWriteTuple(DBFHandle psDBF, int hEntity, void * pRawTuple );
-
-DBFHandle DBFCloneEmpty(DBFHandle psDBF, const char * pszFilename );
+DBFHandle SHPAPI_CALL
+      DBFOpen( const char * pszDBFFile, const char * pszAccess );
+DBFHandle SHPAPI_CALL
+      DBFCreate( const char * pszDBFFile );
+
+int    SHPAPI_CALL
+      DBFGetFieldCount( DBFHandle psDBF );
+int    SHPAPI_CALL
+      DBFGetRecordCount( DBFHandle psDBF );
+int    SHPAPI_CALL
+      DBFAddField( DBFHandle hDBF, const char * pszFieldName,
+                   DBFFieldType eType, int nWidth, int nDecimals );
+
+DBFFieldType SHPAPI_CALL
+      DBFGetFieldInfo( DBFHandle psDBF, int iField, 
+                       char * pszFieldName, int * pnWidth, int * pnDecimals );
+
+int SHPAPI_CALL
+      DBFGetFieldIndex(DBFHandle psDBF, const char *pszFieldName);
+
+int    SHPAPI_CALL
+      DBFReadIntegerAttribute( DBFHandle hDBF, int iShape, int iField );
+double         SHPAPI_CALL
+      DBFReadDoubleAttribute( DBFHandle hDBF, int iShape, int iField );
+const char SHPAPI_CALL1(*)
+      DBFReadStringAttribute( DBFHandle hDBF, int iShape, int iField );
+int     SHPAPI_CALL
+      DBFIsAttributeNULL( DBFHandle hDBF, int iShape, int iField );
+
+int SHPAPI_CALL
+      DBFWriteIntegerAttribute( DBFHandle hDBF, int iShape, int iField, 
+                                int nFieldValue );
+int SHPAPI_CALL
+      DBFWriteDoubleAttribute( DBFHandle hDBF, int iShape, int iField,
+                               double dFieldValue );
+int SHPAPI_CALL
+      DBFWriteStringAttribute( DBFHandle hDBF, int iShape, int iField,
+                               const char * pszFieldValue );
+int SHPAPI_CALL
+     DBFWriteNULLAttribute( DBFHandle hDBF, int iShape, int iField );
+
+const char SHPAPI_CALL1(*)
+      DBFReadTuple(DBFHandle psDBF, int hEntity );
+int SHPAPI_CALL
+      DBFWriteTuple(DBFHandle psDBF, int hEntity, void * pRawTuple );
+
+DBFHandle SHPAPI_CALL
+      DBFCloneEmpty(DBFHandle psDBF, const char * pszFilename );
  
-void   DBFClose( DBFHandle hDBF );
+void   SHPAPI_CALL
+      DBFClose( DBFHandle hDBF );
+char    SHPAPI_CALL
+      DBFGetNativeFieldType( DBFHandle hDBF, int iField );
 
 #ifdef __cplusplus
 }
index d7c475f55bc26f97717255d36755afaa1da74d2a..f5d1f86c21d1f2a74b54010a9332fac68c411f07 100644 (file)
@@ -3,10 +3,10 @@
  *
  * Project:  Shapelib
  * Purpose:  Implementation of core Shapefile read/write functions.
- * Author:   Frank Warmerdam, warmerda@home.com
+ * Author:   Frank Warmerdam, warmerdam@pobox.com
  *
  ******************************************************************************
- * Copyright (c) 1999, Frank Warmerdam
+ * Copyright (c) 1999, 2001, Frank Warmerdam
  *
  * This software is available under the following "MIT Style" license,
  * or at the option of the licensee under the LGPL (see LICENSE.LGPL).  This
  ******************************************************************************
  *
  * $Log$
- * Revision 1.1  2001/07/18 21:42:12  pramsey
- * Initial add of the data loader code.
+ * Revision 1.2  2001/11/01 22:57:11  pramsey
+ * Updated shapelib files from latest CVS version.
+ *
+ * Revision 1.34  2001/11/01 16:29:55  warmerda
+ * move pabyRec into SHPInfo for thread safety
+ *
+ * Revision 1.33  2001/07/03 12:18:15  warmerda
+ * Improved cleanup if SHX not found, provied by Riccardo Cohen.
+ *
+ * Revision 1.32  2001/06/22 01:58:07  warmerda
+ * be more careful about establishing initial bounds in face of NULL shapes
+ *
+ * Revision 1.31  2001/05/31 19:35:29  warmerda
+ * added support for writing null shapes
+ *
+ * Revision 1.30  2001/05/28 12:46:29  warmerda
+ * Add some checking on reasonableness of record count when opening.
+ *
+ * Revision 1.29  2001/05/23 13:36:52  warmerda
+ * added use of SHPAPI_CALL
+ *
+ * Revision 1.28  2001/02/06 22:25:06  warmerda
+ * fixed memory leaks when SHPOpen() fails
+ *
+ * Revision 1.27  2000/07/18 15:21:33  warmerda
+ * added better enforcement of -1 for append in SHPWriteObject
  *
  * Revision 1.26  2000/02/16 16:03:51  warmerda
  * added null shape support
@@ -131,6 +155,7 @@ static char rcsid[] =
 #include <limits.h>
 #include <assert.h>
 #include <stdlib.h>
+#include <string.h>
 
 typedef unsigned char uchar;
 
@@ -152,8 +177,6 @@ typedef int       int32;
 #endif
 
 static int     bBigEndian;
-static uchar   *pabyRec = NULL;
-static int     nBufSize = 0;
 
 
 /************************************************************************/
@@ -302,7 +325,8 @@ static void SHPWriteHeader( SHPHandle psSHP )
 /*      files or either file name.                                      */
 /************************************************************************/
    
-SHPHandle SHPOpen( const char * pszLayer, const char * pszAccess )
+SHPHandle SHPAPI_CALL
+SHPOpen( const char * pszLayer, const char * pszAccess )
 
 {
     char               *pszFullname, *pszBasename;
@@ -335,7 +359,7 @@ SHPHandle SHPOpen( const char * pszLayer, const char * pszAccess )
 /* -------------------------------------------------------------------- */
 /*     Initialize the info structure.                                  */
 /* -------------------------------------------------------------------- */
-    psSHP = (SHPHandle) malloc(sizeof(SHPInfo));
+    psSHP = (SHPHandle) calloc(sizeof(SHPInfo),1);
 
     psSHP->bUpdated = FALSE;
 
@@ -367,7 +391,12 @@ SHPHandle SHPOpen( const char * pszLayer, const char * pszAccess )
     }
     
     if( psSHP->fpSHP == NULL )
+    {
+        free( psSHP );
+        free( pszBasename );
+        free( pszFullname );
         return( NULL );
+    }
 
     sprintf( pszFullname, "%s.shx", pszBasename );
     psSHP->fpSHX = fopen(pszFullname, pszAccess );
@@ -378,7 +407,13 @@ SHPHandle SHPOpen( const char * pszLayer, const char * pszAccess )
     }
     
     if( psSHP->fpSHX == NULL )
+    {
+        fclose( psSHP->fpSHX );
+        free( psSHP );
+        free( pszBasename );
+        free( pszFullname );
         return( NULL );
+    }
 
     free( pszFullname );
     free( pszBasename );
@@ -417,6 +452,16 @@ SHPHandle SHPOpen( const char * pszLayer, const char * pszAccess )
 
     psSHP->nShapeType = pabyBuf[32];
 
+    if( psSHP->nRecords < 0 || psSHP->nRecords > 256000000 )
+    {
+        /* this header appears to be corrupt.  Give up. */
+       fclose( psSHP->fpSHP );
+       fclose( psSHP->fpSHX );
+       free( psSHP );
+
+       return( NULL );
+    }
+
 /* -------------------------------------------------------------------- */
 /*      Read the bounds.                                                */
 /* -------------------------------------------------------------------- */
@@ -492,7 +537,8 @@ SHPHandle SHPOpen( const char * pszLayer, const char * pszAccess )
 /*     Close the .shp and .shx files.                                  */
 /************************************************************************/
 
-void   SHPClose(SHPHandle psSHP )
+void SHPAPI_CALL
+SHPClose(SHPHandle psSHP )
 
 {
 /* -------------------------------------------------------------------- */
@@ -512,14 +558,12 @@ void      SHPClose(SHPHandle psSHP )
     fclose( psSHP->fpSHX );
     fclose( psSHP->fpSHP );
 
-    free( psSHP );
-
-    if( pabyRec != NULL )
+    if( psSHP->pabyRec != NULL )
     {
-        free( pabyRec );
-        pabyRec = NULL;
-        nBufSize = 0;
+        free( psSHP->pabyRec );
     }
+    
+    free( psSHP );
 }
 
 /************************************************************************/
@@ -528,8 +572,9 @@ void        SHPClose(SHPHandle psSHP )
 /*      Fetch general information about the shape file.                 */
 /************************************************************************/
 
-void SHPGetInfo(SHPHandle psSHP, int * pnEntities, int * pnShapeType,
-                double * padfMinBound, double * padfMaxBound )
+void SHPAPI_CALL
+SHPGetInfo(SHPHandle psSHP, int * pnEntities, int * pnShapeType,
+           double * padfMinBound, double * padfMaxBound )
 
 {
     int                i;
@@ -556,7 +601,8 @@ void SHPGetInfo(SHPHandle psSHP, int * pnEntities, int * pnShapeType,
 /*      shape file with read/write access.                              */
 /************************************************************************/
 
-SHPHandle SHPCreate( const char * pszLayer, int nShapeType )
+SHPHandle SHPAPI_CALL
+SHPCreate( const char * pszLayer, int nShapeType )
 
 {
     char       *pszBasename, *pszFullname;
@@ -687,7 +733,8 @@ static void _SHPSetBounds( uchar * pabyRec, SHPObject * psShape )
 /*      SHPCreateObject().                                              */
 /************************************************************************/
 
-void SHPComputeExtents( SHPObject * psObject )
+void SHPAPI_CALL
+SHPComputeExtents( SHPObject * psObject )
 
 {
     int                i;
@@ -724,10 +771,11 @@ void SHPComputeExtents( SHPObject * psObject )
 /*      SHPDestroyObject().                                             */
 /************************************************************************/
 
-SHPObject *SHPCreateObject( int nSHPType, int nShapeId, int nParts,
-                            int * panPartStart, int * panPartType,
-                            int nVertices, double * padfX, double * padfY,
-                            double * padfZ, double * padfM )
+SHPObject SHPAPI_CALL1(*)
+SHPCreateObject( int nSHPType, int nShapeId, int nParts,
+                 int * panPartStart, int * panPartType,
+                 int nVertices, double * padfX, double * padfY,
+                 double * padfZ, double * padfM )
 
 {
     SHPObject  *psObject;
@@ -796,29 +844,31 @@ SHPObject *SHPCreateObject( int nSHPType, int nShapeId, int nParts,
 /*      Capture vertices.  Note that Z and M are optional, but X and    */
 /*      Y are not.                                                      */
 /* -------------------------------------------------------------------- */
-    psObject->padfX = (double *) calloc(sizeof(double),nVertices);
-    psObject->padfY = (double *) calloc(sizeof(double),nVertices);
-    psObject->padfZ = (double *) calloc(sizeof(double),nVertices);
-    psObject->padfM = (double *) calloc(sizeof(double),nVertices);
+    if( nVertices > 0 )
+    {
+        psObject->padfX = (double *) calloc(sizeof(double),nVertices);
+        psObject->padfY = (double *) calloc(sizeof(double),nVertices);
+        psObject->padfZ = (double *) calloc(sizeof(double),nVertices);
+        psObject->padfM = (double *) calloc(sizeof(double),nVertices);
 
-    assert( padfX != NULL );
-    assert( padfY != NULL );
+        assert( padfX != NULL );
+        assert( padfY != NULL );
     
-    for( i = 0; i < nVertices; i++ )
-    {
-        psObject->padfX[i] = padfX[i];
-        psObject->padfY[i] = padfY[i];
-        if( padfZ != NULL && bHasZ )
-            psObject->padfZ[i] = padfZ[i];
-        if( padfM != NULL && bHasM )
-            psObject->padfM[i] = padfM[i];
+        for( i = 0; i < nVertices; i++ )
+        {
+            psObject->padfX[i] = padfX[i];
+            psObject->padfY[i] = padfY[i];
+            if( padfZ != NULL && bHasZ )
+                psObject->padfZ[i] = padfZ[i];
+            if( padfM != NULL && bHasM )
+                psObject->padfM[i] = padfM[i];
+        }
     }
 
 /* -------------------------------------------------------------------- */
 /*      Compute the extents.                                            */
 /* -------------------------------------------------------------------- */
     psObject->nVertices = nVertices;
-    
     SHPComputeExtents( psObject );
 
     return( psObject );
@@ -831,9 +881,10 @@ SHPObject *SHPCreateObject( int nSHPType, int nShapeId, int nParts,
 /*      SHPDestroyObject().                                             */
 /************************************************************************/
 
-SHPObject *SHPCreateSimpleObject( int nSHPType, int nVertices,
-                                  double * padfX, double * padfY,
-                                  double * padfZ )
+SHPObject SHPAPI_CALL1(*)
+SHPCreateSimpleObject( int nSHPType, int nVertices,
+                       double * padfX, double * padfY,
+                       double * padfZ )
 
 {
     return( SHPCreateObject( nSHPType, -1, 0, NULL, NULL,
@@ -847,7 +898,8 @@ SHPObject *SHPCreateSimpleObject( int nSHPType, int nVertices,
 /*      only possible to write vertices at the end of the file.         */
 /************************************************************************/
 
-int SHPWriteObject(SHPHandle psSHP, int nShapeId, SHPObject * psObject )
+int SHPAPI_CALL
+SHPWriteObject(SHPHandle psSHP, int nShapeId, SHPObject * psObject )
                      
 {
     int                nRecordOffset, i, nRecordSize;
@@ -860,7 +912,19 @@ int SHPWriteObject(SHPHandle psSHP, int nShapeId, SHPObject * psObject )
 /*      Ensure that shape object matches the type of the file it is     */
 /*      being written to.                                               */
 /* -------------------------------------------------------------------- */
-    assert( psObject->nSHPType == psSHP->nShapeType );
+    assert( psObject->nSHPType == psSHP->nShapeType 
+            || psObject->nSHPType == SHPT_NULL );
+
+/* -------------------------------------------------------------------- */
+/*      Ensure that -1 is used for appends.  Either blow an             */
+/*      assertion, or if they are disabled, set the shapeid to -1       */
+/*      for appends.                                                    */
+/* -------------------------------------------------------------------- */
+    assert( nShapeId == -1 
+            || (nShapeId >= 0 && nShapeId < psSHP->nRecords) );
+
+    if( nShapeId != -1 && nShapeId >= psSHP->nRecords )
+        nShapeId = -1;
 
 /* -------------------------------------------------------------------- */
 /*      Add the new entity to the in memory index.                      */
@@ -870,9 +934,9 @@ int SHPWriteObject(SHPHandle psSHP, int nShapeId, SHPObject * psObject )
        psSHP->nMaxRecords =(int) ( psSHP->nMaxRecords * 1.3 + 100);
 
        psSHP->panRecOffset = (int *) 
-         SfRealloc(psSHP->panRecOffset,sizeof(int) * psSHP->nMaxRecords );
+            SfRealloc(psSHP->panRecOffset,sizeof(int) * psSHP->nMaxRecords );
        psSHP->panRecSize = (int *) 
-         SfRealloc(psSHP->panRecSize,sizeof(int) * psSHP->nMaxRecords );
+            SfRealloc(psSHP->panRecSize,sizeof(int) * psSHP->nMaxRecords );
     }
 
 /* -------------------------------------------------------------------- */
@@ -884,13 +948,13 @@ int SHPWriteObject(SHPHandle psSHP, int nShapeId, SHPObject * psObject )
 /* -------------------------------------------------------------------- */
 /*  Extract vertices for a Polygon or Arc.                             */
 /* -------------------------------------------------------------------- */
-    if( psSHP->nShapeType == SHPT_POLYGON
-        || psSHP->nShapeType == SHPT_POLYGONZ
-        || psSHP->nShapeType == SHPT_POLYGONM
-        || psSHP->nShapeType == SHPT_ARC 
-        || psSHP->nShapeType == SHPT_ARCZ
-        || psSHP->nShapeType == SHPT_ARCM
-        || psSHP->nShapeType == SHPT_MULTIPATCH )
+    if( psObject->nSHPType == SHPT_POLYGON
+        || psObject->nSHPType == SHPT_POLYGONZ
+        || psObject->nSHPType == SHPT_POLYGONM
+        || psObject->nSHPType == SHPT_ARC 
+        || psObject->nSHPType == SHPT_ARCZ
+        || psObject->nSHPType == SHPT_ARCM
+        || psObject->nSHPType == SHPT_MULTIPATCH )
     {
        int32           nPoints, nParts;
        int             i;
@@ -922,7 +986,7 @@ int SHPWriteObject(SHPHandle psSHP, int nShapeId, SHPObject * psObject )
         /*
          * Write multipatch part types if needed.
          */
-        if( psSHP->nShapeType == SHPT_MULTIPATCH )
+        if( psObject->nSHPType == SHPT_MULTIPATCH )
         {
             memcpy( pabyRec + nRecordSize, psObject->panPartType,
                     4*psObject->nParts );
@@ -953,9 +1017,9 @@ int SHPWriteObject(SHPHandle psSHP, int nShapeId, SHPObject * psObject )
         /*
          * Write the Z coordinates (if any).
          */
-        if( psSHP->nShapeType == SHPT_POLYGONZ
-            || psSHP->nShapeType == SHPT_ARCZ
-            || psSHP->nShapeType == SHPT_MULTIPATCH )
+        if( psObject->nSHPType == SHPT_POLYGONZ
+            || psObject->nSHPType == SHPT_ARCZ
+            || psObject->nSHPType == SHPT_MULTIPATCH )
         {
             ByteCopy( &(psObject->dfZMin), pabyRec + nRecordSize, 8 );
             if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize );
@@ -976,13 +1040,13 @@ int SHPWriteObject(SHPHandle psSHP, int nShapeId, SHPObject * psObject )
         /*
          * Write the M values, if any.
          */
-        if( psSHP->nShapeType == SHPT_POLYGONM
-            || psSHP->nShapeType == SHPT_ARCM
+        if( psObject->nSHPType == SHPT_POLYGONM
+            || psObject->nSHPType == SHPT_ARCM
 #ifndef DISABLE_MULTIPATCH_MEASURE            
-            || psSHP->nShapeType == SHPT_MULTIPATCH
+            || psObject->nSHPType == SHPT_MULTIPATCH
 #endif            
-            || psSHP->nShapeType == SHPT_POLYGONZ
-            || psSHP->nShapeType == SHPT_ARCZ )
+            || psObject->nSHPType == SHPT_POLYGONZ
+            || psObject->nSHPType == SHPT_ARCZ )
         {
             ByteCopy( &(psObject->dfMMin), pabyRec + nRecordSize, 8 );
             if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize );
@@ -1004,9 +1068,9 @@ int SHPWriteObject(SHPHandle psSHP, int nShapeId, SHPObject * psObject )
 /* -------------------------------------------------------------------- */
 /*  Extract vertices for a MultiPoint.                                 */
 /* -------------------------------------------------------------------- */
-    else if( psSHP->nShapeType == SHPT_MULTIPOINT
-             || psSHP->nShapeType == SHPT_MULTIPOINTZ
-             || psSHP->nShapeType == SHPT_MULTIPOINTM )
+    else if( psObject->nSHPType == SHPT_MULTIPOINT
+             || psObject->nSHPType == SHPT_MULTIPOINTZ
+             || psObject->nSHPType == SHPT_MULTIPOINTM )
     {
        int32           nPoints;
        int             i;
@@ -1029,7 +1093,7 @@ int SHPWriteObject(SHPHandle psSHP, int nShapeId, SHPObject * psObject )
 
        nRecordSize = 48 + 16 * psObject->nVertices;
 
-        if( psSHP->nShapeType == SHPT_MULTIPOINTZ )
+        if( psObject->nSHPType == SHPT_MULTIPOINTZ )
         {
             ByteCopy( &(psObject->dfZMin), pabyRec + nRecordSize, 8 );
             if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize );
@@ -1047,8 +1111,8 @@ int SHPWriteObject(SHPHandle psSHP, int nShapeId, SHPObject * psObject )
             }
         }
 
-        if( psSHP->nShapeType == SHPT_MULTIPOINTZ
-            || psSHP->nShapeType == SHPT_MULTIPOINTM )
+        if( psObject->nSHPType == SHPT_MULTIPOINTZ
+            || psObject->nSHPType == SHPT_MULTIPOINTM )
         {
             ByteCopy( &(psObject->dfMMin), pabyRec + nRecordSize, 8 );
             if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize );
@@ -1068,11 +1132,11 @@ int SHPWriteObject(SHPHandle psSHP, int nShapeId, SHPObject * psObject )
     }
 
 /* -------------------------------------------------------------------- */
-/*      Extract vertices for a point.                                   */
+/*      Write point.                                                   */
 /* -------------------------------------------------------------------- */
-    else if( psSHP->nShapeType == SHPT_POINT
-             || psSHP->nShapeType == SHPT_POINTZ
-             || psSHP->nShapeType == SHPT_POINTM )
+    else if( psObject->nSHPType == SHPT_POINT
+             || psObject->nSHPType == SHPT_POINTZ
+             || psObject->nSHPType == SHPT_POINTM )
     {
        ByteCopy( psObject->padfX, pabyRec + 12, 8 );
        ByteCopy( psObject->padfY, pabyRec + 20, 8 );
@@ -1082,15 +1146,15 @@ int SHPWriteObject(SHPHandle psSHP, int nShapeId, SHPObject * psObject )
 
         nRecordSize = 28;
         
-        if( psSHP->nShapeType == SHPT_POINTZ )
+        if( psObject->nSHPType == SHPT_POINTZ )
         {
             ByteCopy( psObject->padfZ, pabyRec + nRecordSize, 8 );
             if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize );
             nRecordSize += 8;
         }
         
-        if( psSHP->nShapeType == SHPT_POINTZ
-            || psSHP->nShapeType == SHPT_POINTM )
+        if( psObject->nSHPType == SHPT_POINTZ
+            || psObject->nSHPType == SHPT_POINTM )
         {
             ByteCopy( psObject->padfM, pabyRec + nRecordSize, 8 );
             if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize );
@@ -1098,6 +1162,14 @@ int SHPWriteObject(SHPHandle psSHP, int nShapeId, SHPObject * psObject )
         }
     }
 
+/* -------------------------------------------------------------------- */
+/*      Not much to do for null geometries.                             */
+/* -------------------------------------------------------------------- */
+    else if( psObject->nSHPType == SHPT_NULL )
+    {
+        nRecordSize = 12;
+    }
+
     else
     {
         /* unknown type */
@@ -1134,7 +1206,7 @@ int SHPWriteObject(SHPHandle psSHP, int nShapeId, SHPObject * psObject )
     if( !bBigEndian ) SwapWord( 4, &i32 );
     ByteCopy( &i32, pabyRec + 4, 4 );
 
-    i32 = psSHP->nShapeType;                           /* shape type */
+    i32 = psObject->nSHPType;                          /* shape type */
     if( bBigEndian ) SwapWord( 4, &i32 );
     ByteCopy( &i32, pabyRec + 8, 4 );
 
@@ -1154,12 +1226,16 @@ int SHPWriteObject(SHPHandle psSHP, int nShapeId, SHPObject * psObject )
 /* -------------------------------------------------------------------- */
 /*     Expand file wide bounds based on this shape.                    */
 /* -------------------------------------------------------------------- */
-    if( psSHP->nRecords == 1 )
+    if( psSHP->adBoundsMin[0] == 0.0
+        && psSHP->adBoundsMax[0] == 0.0
+        && psSHP->adBoundsMin[1] == 0.0
+        && psSHP->adBoundsMax[1] == 0.0 
+        && psObject->nSHPType != SHPT_NULL )
     {
-       psSHP->adBoundsMin[0] = psSHP->adBoundsMax[0] = psObject->padfX[0];
-       psSHP->adBoundsMin[1] = psSHP->adBoundsMax[1] = psObject->padfY[0];
-       psSHP->adBoundsMin[2] = psSHP->adBoundsMax[2] = psObject->padfZ[0];
-       psSHP->adBoundsMin[3] = psSHP->adBoundsMax[3] = psObject->padfM[0];
+        psSHP->adBoundsMin[0] = psSHP->adBoundsMax[0] = psObject->padfX[0];
+        psSHP->adBoundsMin[1] = psSHP->adBoundsMax[1] = psObject->padfY[0];
+        psSHP->adBoundsMin[2] = psSHP->adBoundsMax[2] = psObject->padfZ[0];
+        psSHP->adBoundsMin[3] = psSHP->adBoundsMax[3] = psObject->padfM[0];
     }
 
     for( i = 0; i < psObject->nVertices; i++ )
@@ -1184,7 +1260,8 @@ int SHPWriteObject(SHPHandle psSHP, int nShapeId, SHPObject * psObject )
 /*     for one shape.                                                  */
 /************************************************************************/
 
-SHPObject *SHPReadObject( SHPHandle psSHP, int hEntity )
+SHPObject SHPAPI_CALL1(*)
+SHPReadObject( SHPHandle psSHP, int hEntity )
 
 {
     SHPObject          *psShape;
@@ -1198,17 +1275,17 @@ SHPObject *SHPReadObject( SHPHandle psSHP, int hEntity )
 /* -------------------------------------------------------------------- */
 /*      Ensure our record buffer is large enough.                       */
 /* -------------------------------------------------------------------- */
-    if( psSHP->panRecSize[hEntity]+8 > nBufSize )
+    if( psSHP->panRecSize[hEntity]+8 > psSHP->nBufSize )
     {
-       nBufSize = psSHP->panRecSize[hEntity]+8;
-       pabyRec = (uchar *) SfRealloc(pabyRec,nBufSize);
+       psSHP->nBufSize = psSHP->panRecSize[hEntity]+8;
+       psSHP->pabyRec = (uchar *) SfRealloc(psSHP->pabyRec,psSHP->nBufSize);
     }
 
 /* -------------------------------------------------------------------- */
 /*      Read the record.                                                */
 /* -------------------------------------------------------------------- */
     fseek( psSHP->fpSHP, psSHP->panRecOffset[hEntity], 0 );
-    fread( pabyRec, psSHP->panRecSize[hEntity]+8, 1, psSHP->fpSHP );
+    fread( psSHP->pabyRec, psSHP->panRecSize[hEntity]+8, 1, psSHP->fpSHP );
 
 /* -------------------------------------------------------------------- */
 /*     Allocate and minimally initialize the object.                   */
@@ -1216,7 +1293,7 @@ SHPObject *SHPReadObject( SHPHandle psSHP, int hEntity )
     psShape = (SHPObject *) calloc(1,sizeof(SHPObject));
     psShape->nShapeId = hEntity;
 
-    memcpy( &psShape->nSHPType, pabyRec + 8, 4 );
+    memcpy( &psShape->nSHPType, psSHP->pabyRec + 8, 4 );
     if( bBigEndian ) SwapWord( 4, &(psShape->nSHPType) );
 
 /* ==================================================================== */
@@ -1235,10 +1312,10 @@ SHPObject *SHPReadObject( SHPHandle psSHP, int hEntity )
 /* -------------------------------------------------------------------- */
 /*     Get the X/Y bounds.                                             */
 /* -------------------------------------------------------------------- */
-        memcpy( &(psShape->dfXMin), pabyRec + 8 +  4, 8 );
-        memcpy( &(psShape->dfYMin), pabyRec + 8 + 12, 8 );
-        memcpy( &(psShape->dfXMax), pabyRec + 8 + 20, 8 );
-        memcpy( &(psShape->dfYMax), pabyRec + 8 + 28, 8 );
+        memcpy( &(psShape->dfXMin), psSHP->pabyRec + 8 +  4, 8 );
+        memcpy( &(psShape->dfYMin), psSHP->pabyRec + 8 + 12, 8 );
+        memcpy( &(psShape->dfXMax), psSHP->pabyRec + 8 + 20, 8 );
+        memcpy( &(psShape->dfYMax), psSHP->pabyRec + 8 + 28, 8 );
 
        if( bBigEndian ) SwapWord( 8, &(psShape->dfXMin) );
        if( bBigEndian ) SwapWord( 8, &(psShape->dfYMin) );
@@ -1249,8 +1326,8 @@ SHPObject *SHPReadObject( SHPHandle psSHP, int hEntity )
 /*      Extract part/point count, and build vertex and part arrays      */
 /*      to proper size.                                                 */
 /* -------------------------------------------------------------------- */
-       memcpy( &nPoints, pabyRec + 40 + 8, 4 );
-       memcpy( &nParts, pabyRec + 36 + 8, 4 );
+       memcpy( &nPoints, psSHP->pabyRec + 40 + 8, 4 );
+       memcpy( &nParts, psSHP->pabyRec + 36 + 8, 4 );
 
        if( bBigEndian ) SwapWord( 4, &nPoints );
        if( bBigEndian ) SwapWord( 4, &nParts );
@@ -1271,7 +1348,7 @@ SHPObject *SHPReadObject( SHPHandle psSHP, int hEntity )
 /* -------------------------------------------------------------------- */
 /*      Copy out the part array from the record.                        */
 /* -------------------------------------------------------------------- */
-       memcpy( psShape->panPartStart, pabyRec + 44 + 8, 4 * nParts );
+       memcpy( psShape->panPartStart, psSHP->pabyRec + 44 + 8, 4 * nParts );
        for( i = 0; i < nParts; i++ )
        {
            if( bBigEndian ) SwapWord( 4, psShape->panPartStart+i );
@@ -1284,7 +1361,7 @@ SHPObject *SHPReadObject( SHPHandle psSHP, int hEntity )
 /* -------------------------------------------------------------------- */
         if( psShape->nSHPType == SHPT_MULTIPATCH )
         {
-            memcpy( psShape->panPartType, pabyRec + nOffset, 4*nParts );
+            memcpy( psShape->panPartType, psSHP->pabyRec + nOffset, 4*nParts );
             for( i = 0; i < nParts; i++ )
             {
                 if( bBigEndian ) SwapWord( 4, psShape->panPartType+i );
@@ -1299,11 +1376,11 @@ SHPObject *SHPReadObject( SHPHandle psSHP, int hEntity )
        for( i = 0; i < nPoints; i++ )
        {
            memcpy(psShape->padfX + i,
-                  pabyRec + nOffset + i * 16,
+                  psSHP->pabyRec + nOffset + i * 16,
                   8 );
 
            memcpy(psShape->padfY + i,
-                  pabyRec + nOffset + i * 16 + 8,
+                  psSHP->pabyRec + nOffset + i * 16 + 8,
                   8 );
 
            if( bBigEndian ) SwapWord( 8, psShape->padfX + i );
@@ -1319,8 +1396,8 @@ SHPObject *SHPReadObject( SHPHandle psSHP, int hEntity )
             || psShape->nSHPType == SHPT_ARCZ
             || psShape->nSHPType == SHPT_MULTIPATCH )
         {
-            memcpy( &(psShape->dfZMin), pabyRec + nOffset, 8 );
-            memcpy( &(psShape->dfZMax), pabyRec + nOffset + 8, 8 );
+            memcpy( &(psShape->dfZMin), psSHP->pabyRec + nOffset, 8 );
+            memcpy( &(psShape->dfZMax), psSHP->pabyRec + nOffset + 8, 8 );
             
             if( bBigEndian ) SwapWord( 8, &(psShape->dfZMin) );
             if( bBigEndian ) SwapWord( 8, &(psShape->dfZMax) );
@@ -1328,7 +1405,7 @@ SHPObject *SHPReadObject( SHPHandle psSHP, int hEntity )
             for( i = 0; i < nPoints; i++ )
             {
                 memcpy( psShape->padfZ + i,
-                        pabyRec + nOffset + 16 + i*8, 8 );
+                        psSHP->pabyRec + nOffset + 16 + i*8, 8 );
                 if( bBigEndian ) SwapWord( 8, psShape->padfZ + i );
             }
 
@@ -1343,8 +1420,8 @@ SHPObject *SHPReadObject( SHPHandle psSHP, int hEntity )
 /* -------------------------------------------------------------------- */
         if( psSHP->panRecSize[hEntity]+8 >= nOffset + 16 + 8*nPoints )
         {
-            memcpy( &(psShape->dfMMin), pabyRec + nOffset, 8 );
-            memcpy( &(psShape->dfMMax), pabyRec + nOffset + 8, 8 );
+            memcpy( &(psShape->dfMMin), psSHP->pabyRec + nOffset, 8 );
+            memcpy( &(psShape->dfMMax), psSHP->pabyRec + nOffset + 8, 8 );
             
             if( bBigEndian ) SwapWord( 8, &(psShape->dfMMin) );
             if( bBigEndian ) SwapWord( 8, &(psShape->dfMMax) );
@@ -1352,7 +1429,7 @@ SHPObject *SHPReadObject( SHPHandle psSHP, int hEntity )
             for( i = 0; i < nPoints; i++ )
             {
                 memcpy( psShape->padfM + i,
-                        pabyRec + nOffset + 16 + i*8, 8 );
+                        psSHP->pabyRec + nOffset + 16 + i*8, 8 );
                 if( bBigEndian ) SwapWord( 8, psShape->padfM + i );
             }
         }
@@ -1369,7 +1446,7 @@ SHPObject *SHPReadObject( SHPHandle psSHP, int hEntity )
        int32           nPoints;
        int             i, nOffset;
 
-       memcpy( &nPoints, pabyRec + 44, 4 );
+       memcpy( &nPoints, psSHP->pabyRec + 44, 4 );
        if( bBigEndian ) SwapWord( 4, &nPoints );
 
        psShape->nVertices = nPoints;
@@ -1380,8 +1457,8 @@ SHPObject *SHPReadObject( SHPHandle psSHP, int hEntity )
 
        for( i = 0; i < nPoints; i++ )
        {
-           memcpy(psShape->padfX+i, pabyRec + 48 + 16 * i, 8 );
-           memcpy(psShape->padfY+i, pabyRec + 48 + 16 * i + 8, 8 );
+           memcpy(psShape->padfX+i, psSHP->pabyRec + 48 + 16 * i, 8 );
+           memcpy(psShape->padfY+i, psSHP->pabyRec + 48 + 16 * i + 8, 8 );
 
            if( bBigEndian ) SwapWord( 8, psShape->padfX + i );
            if( bBigEndian ) SwapWord( 8, psShape->padfY + i );
@@ -1392,10 +1469,10 @@ SHPObject *SHPReadObject( SHPHandle psSHP, int hEntity )
 /* -------------------------------------------------------------------- */
 /*     Get the X/Y bounds.                                             */
 /* -------------------------------------------------------------------- */
-        memcpy( &(psShape->dfXMin), pabyRec + 8 +  4, 8 );
-        memcpy( &(psShape->dfYMin), pabyRec + 8 + 12, 8 );
-        memcpy( &(psShape->dfXMax), pabyRec + 8 + 20, 8 );
-        memcpy( &(psShape->dfYMax), pabyRec + 8 + 28, 8 );
+        memcpy( &(psShape->dfXMin), psSHP->pabyRec + 8 +  4, 8 );
+        memcpy( &(psShape->dfYMin), psSHP->pabyRec + 8 + 12, 8 );
+        memcpy( &(psShape->dfXMax), psSHP->pabyRec + 8 + 20, 8 );
+        memcpy( &(psShape->dfYMax), psSHP->pabyRec + 8 + 28, 8 );
 
        if( bBigEndian ) SwapWord( 8, &(psShape->dfXMin) );
        if( bBigEndian ) SwapWord( 8, &(psShape->dfYMin) );
@@ -1407,8 +1484,8 @@ SHPObject *SHPReadObject( SHPHandle psSHP, int hEntity )
 /* -------------------------------------------------------------------- */
         if( psShape->nSHPType == SHPT_MULTIPOINTZ )
         {
-            memcpy( &(psShape->dfZMin), pabyRec + nOffset, 8 );
-            memcpy( &(psShape->dfZMax), pabyRec + nOffset + 8, 8 );
+            memcpy( &(psShape->dfZMin), psSHP->pabyRec + nOffset, 8 );
+            memcpy( &(psShape->dfZMax), psSHP->pabyRec + nOffset + 8, 8 );
             
             if( bBigEndian ) SwapWord( 8, &(psShape->dfZMin) );
             if( bBigEndian ) SwapWord( 8, &(psShape->dfZMax) );
@@ -1416,7 +1493,7 @@ SHPObject *SHPReadObject( SHPHandle psSHP, int hEntity )
             for( i = 0; i < nPoints; i++ )
             {
                 memcpy( psShape->padfZ + i,
-                        pabyRec + nOffset + 16 + i*8, 8 );
+                        psSHP->pabyRec + nOffset + 16 + i*8, 8 );
                 if( bBigEndian ) SwapWord( 8, psShape->padfZ + i );
             }
 
@@ -1431,8 +1508,8 @@ SHPObject *SHPReadObject( SHPHandle psSHP, int hEntity )
 /* -------------------------------------------------------------------- */
         if( psSHP->panRecSize[hEntity]+8 >= nOffset + 16 + 8*nPoints )
         {
-            memcpy( &(psShape->dfMMin), pabyRec + nOffset, 8 );
-            memcpy( &(psShape->dfMMax), pabyRec + nOffset + 8, 8 );
+            memcpy( &(psShape->dfMMin), psSHP->pabyRec + nOffset, 8 );
+            memcpy( &(psShape->dfMMax), psSHP->pabyRec + nOffset + 8, 8 );
             
             if( bBigEndian ) SwapWord( 8, &(psShape->dfMMin) );
             if( bBigEndian ) SwapWord( 8, &(psShape->dfMMax) );
@@ -1440,7 +1517,7 @@ SHPObject *SHPReadObject( SHPHandle psSHP, int hEntity )
             for( i = 0; i < nPoints; i++ )
             {
                 memcpy( psShape->padfM + i,
-                        pabyRec + nOffset + 16 + i*8, 8 );
+                        psSHP->pabyRec + nOffset + 16 + i*8, 8 );
                 if( bBigEndian ) SwapWord( 8, psShape->padfM + i );
             }
         }
@@ -1461,8 +1538,8 @@ SHPObject *SHPReadObject( SHPHandle psSHP, int hEntity )
         psShape->padfZ = (double *) calloc(1,sizeof(double));
         psShape->padfM = (double *) calloc(1,sizeof(double));
 
-       memcpy( psShape->padfX, pabyRec + 12, 8 );
-       memcpy( psShape->padfY, pabyRec + 20, 8 );
+       memcpy( psShape->padfX, psSHP->pabyRec + 12, 8 );
+       memcpy( psShape->padfY, psSHP->pabyRec + 20, 8 );
 
        if( bBigEndian ) SwapWord( 8, psShape->padfX );
        if( bBigEndian ) SwapWord( 8, psShape->padfY );
@@ -1474,7 +1551,7 @@ SHPObject *SHPReadObject( SHPHandle psSHP, int hEntity )
 /* -------------------------------------------------------------------- */
         if( psShape->nSHPType == SHPT_POINTZ )
         {
-            memcpy( psShape->padfZ, pabyRec + nOffset, 8 );
+            memcpy( psShape->padfZ, psSHP->pabyRec + nOffset, 8 );
         
             if( bBigEndian ) SwapWord( 8, psShape->padfZ );
             
@@ -1489,7 +1566,7 @@ SHPObject *SHPReadObject( SHPHandle psSHP, int hEntity )
 /* -------------------------------------------------------------------- */
         if( psSHP->panRecSize[hEntity]+8 >= nOffset + 8 )
         {
-            memcpy( psShape->padfM, pabyRec + nOffset, 8 );
+            memcpy( psShape->padfM, psSHP->pabyRec + nOffset, 8 );
         
             if( bBigEndian ) SwapWord( 8, psShape->padfM );
         }
@@ -1511,12 +1588,13 @@ SHPObject *SHPReadObject( SHPHandle psSHP, int hEntity )
 /*                            SHPTypeName()                             */
 /************************************************************************/
 
-const char *SHPTypeName( int nSHPType )
+const char SHPAPI_CALL1(*)
+SHPTypeName( int nSHPType )
 
 {
     switch( nSHPType )
     {
-      case 0:
+      case SHPT_NULL:
         return "NullShape";
 
       case SHPT_POINT:
@@ -1567,7 +1645,8 @@ const char *SHPTypeName( int nSHPType )
 /*                          SHPPartTypeName()                           */
 /************************************************************************/
 
-const char *SHPPartTypeName( int nPartType )
+const char SHPAPI_CALL1(*)
+SHPPartTypeName( int nPartType )
 
 {
     switch( nPartType )
@@ -1599,7 +1678,8 @@ const char *SHPPartTypeName( int nPartType )
 /*                          SHPDestroyObject()                          */
 /************************************************************************/
 
-void SHPDestroyObject( SHPObject * psShape )
+void SHPAPI_CALL
+SHPDestroyObject( SHPObject * psShape )
 
 {
     if( psShape == NULL )