LCOV - code coverage report
Current view: directory - ogr/ogrsf_frmts/avc - avc_binwr.c (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 695 0 0.0 %
Date: 2012-12-26 Functions: 31 0 0.0 %

       1                 : /* $Id: avc_binwr.c,v 1.18 2008/07/23 20:51:38 dmorissette Exp $
       2                 :  *
       3                 :  * Name:     avc_binwr.c
       4                 :  * Project:  Arc/Info vector coverage (AVC)  E00->BIN conversion library
       5                 :  * Language: ANSI C
       6                 :  * Purpose:  Binary files access functions (write mode).
       7                 :  * Author:   Daniel Morissette, dmorissette@dmsolutions.ca
       8                 :  *
       9                 :  **********************************************************************
      10                 :  * Copyright (c) 1999-2001, Daniel Morissette
      11                 :  *
      12                 :  * Permission is hereby granted, free of charge, to any person obtaining a
      13                 :  * copy of this software and associated documentation files (the "Software"),
      14                 :  * to deal in the Software without restriction, including without limitation
      15                 :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      16                 :  * and/or sell copies of the Software, and to permit persons to whom the
      17                 :  * Software is furnished to do so, subject to the following conditions:
      18                 :  * 
      19                 :  * The above copyright notice and this permission notice shall be included
      20                 :  * in all copies or substantial portions of the Software.
      21                 :  * 
      22                 :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      23                 :  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      24                 :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
      25                 :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      26                 :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      27                 :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
      28                 :  * DEALINGS IN THE SOFTWARE.
      29                 :  **********************************************************************
      30                 :  *
      31                 :  * $Log: avc_binwr.c,v $
      32                 :  * Revision 1.18  2008/07/23 20:51:38  dmorissette
      33                 :  * Fixed GCC 4.1.x compile warnings related to use of char vs unsigned char
      34                 :  * (GDAL/OGR ticket http://trac.osgeo.org/gdal/ticket/2495)
      35                 :  *
      36                 :  * Revision 1.17  2006/06/14 16:31:28  daniel
      37                 :  * Added support for AVCCoverPC2 type (bug 1491)
      38                 :  *
      39                 :  * Revision 1.16  2005/06/03 03:49:58  daniel
      40                 :  * Update email address, website url, and copyright dates
      41                 :  *
      42                 :  * Revision 1.15  2001/07/06 05:09:33  daniel
      43                 :  * Removed #ifdef around fseek to fix NT4 drive problem since ANSI-C requires
      44                 :  * an fseek() between read and write operations so this applies to Unix too.
      45                 :  *
      46                 :  * Revision 1.14  2001/07/06 04:25:00  daniel
      47                 :  * Fixed a problem writing arc.dir on NT4 networked drives in an empty dir.
      48                 :  *
      49                 :  * Revision 1.13  2000/10/16 16:13:29  daniel
      50                 :  * Fixed sHeader.nPrecision when writing PC TXT files
      51                 :  *
      52                 :  * Revision 1.12  2000/09/26 21:40:18  daniel
      53                 :  * Fixed writing of PC Coverage TXT... they're different from V7 TXT
      54                 :  *
      55                 :  * Revision 1.11  2000/09/26 20:21:04  daniel
      56                 :  * Added AVCCoverPC write
      57                 :  *
      58                 :  * Revision 1.10  2000/09/22 19:45:20  daniel
      59                 :  * Switch to MIT-style license
      60                 :  *
      61                 :  * Revision 1.9  2000/05/29 15:31:30  daniel
      62                 :  * Added Japanese DBCS support
      63                 :  *
      64                 :  * Revision 1.8  2000/01/10 02:55:12  daniel
      65                 :  * Added call to AVCAdjustCaseSensitiveFilename() when creating tables
      66                 :  *
      67                 :  * Revision 1.7  1999/12/24 07:18:34  daniel
      68                 :  * Added PC Arc/Info coverages support
      69                 :  *
      70                 :  * Revision 1.6  1999/08/26 17:26:09  daniel
      71                 :  * Removed printf() messages used in Windows tests
      72                 :  *
      73                 :  * Revision 1.5  1999/08/23 18:18:51  daniel
      74                 :  * Fixed memory leak and some VC++ warnings
      75                 :  *
      76                 :  * Revision 1.4  1999/06/08 22:08:14  daniel
      77                 :  * Modified CreateTable() to overwrite existing arc.dir entries if necessary
      78                 :  *
      79                 :  * Revision 1.3  1999/06/08 18:24:32  daniel
      80                 :  * Fixed some problems with '/' vs '\\' on Windows
      81                 :  *
      82                 :  * Revision 1.2  1999/05/17 16:17:36  daniel
      83                 :  * Added RXP + TXT/TX6/TX7 write support
      84                 :  *
      85                 :  * Revision 1.1  1999/05/11 02:34:46  daniel
      86                 :  * Initial revision
      87                 :  *
      88                 :  **********************************************************************/
      89                 : 
      90                 : #include "avc.h"
      91                 : 
      92                 : #include <ctype.h>  /* tolower() */
      93                 : 
      94                 : /*=====================================================================
      95                 :  * Stuff related to writing the binary coverage files
      96                 :  *====================================================================*/
      97                 : 
      98                 : static void    _AVCBinWriteCloseTable(AVCBinFile *psFile);
      99                 : 
     100                 : static AVCBinFile *_AVCBinWriteCreateDBFTable(const char *pszPath, 
     101                 :                                               const char *pszCoverName,
     102                 :                                               AVCTableDef *psSrcTableDef,
     103                 :                                               AVCCoverType eCoverType,
     104                 :                                               int nPrecision, 
     105                 :                                               AVCDBCSInfo *psDBCSInfo);
     106                 : 
     107                 : /**********************************************************************
     108                 :  *                          AVCBinWriteCreate()
     109                 :  *
     110                 :  * Open a coverage file for writing, write a header if applicable, and
     111                 :  * initialize the handle to be ready to write objects to the file.
     112                 :  *
     113                 :  * pszPath is the coverage (or info directory) path, terminated by
     114                 :  *         a '/' or a '\\'
     115                 :  * pszName is the name of the file to create relative to this directory.
     116                 :  *
     117                 :  * Note: For most file types except tables, passing pszPath="" and 
     118                 :  * including the coverage path as part of pszName instead would work.
     119                 :  *
     120                 :  * Returns a valid AVCBinFile handle, or NULL if the file could
     121                 :  * not be created.
     122                 :  *
     123                 :  * AVCBinClose() will eventually have to be called to release the 
     124                 :  * resources used by the AVCBinFile structure.
     125                 :  **********************************************************************/
     126               0 : AVCBinFile *AVCBinWriteCreate(const char *pszPath, const char *pszName, 
     127                 :                               AVCCoverType eCoverType,
     128                 :                               AVCFileType eType, int nPrecision,
     129                 :                               AVCDBCSInfo *psDBCSInfo)
     130                 : {
     131                 :     AVCBinFile   *psFile;
     132               0 :     char         *pszFname = NULL, *pszExt;
     133               0 :     GBool        bCreateIndex = FALSE;
     134                 :     int          nLen;
     135                 : 
     136                 :     /*-----------------------------------------------------------------
     137                 :      * Make sure precision value is valid (AVC_DEFAULT_PREC is NOT valid)
     138                 :      *----------------------------------------------------------------*/
     139               0 :     if (nPrecision!=AVC_SINGLE_PREC && nPrecision!=AVC_DOUBLE_PREC)
     140                 :     {
     141               0 :         CPLError(CE_Failure, CPLE_IllegalArg,
     142                 :                  "AVCBinWriteCreate(): Invalid precision parameter "
     143                 :                  "(value must be AVC_SINGLE_PREC or AVC_DOUBLE_PREC)");
     144               0 :         return NULL;
     145                 :     }
     146                 : 
     147                 :     /*-----------------------------------------------------------------
     148                 :      * The case of INFO tables is a bit different...
     149                 :      * tables have to be created through a separate function.
     150                 :      *----------------------------------------------------------------*/
     151               0 :     if (eType == AVCFileTABLE)
     152                 :     {
     153               0 :         CPLError(CE_Failure, CPLE_AssertionFailed,
     154                 :                  "AVCBinWriteCreate(): TABLEs must be created using "
     155                 :                  "AVCBinWriteCreateTable()");
     156               0 :         return NULL;
     157                 :     }
     158                 : 
     159                 :     /*-----------------------------------------------------------------
     160                 :      * Alloc and init the AVCBinFile struct.
     161                 :      *----------------------------------------------------------------*/
     162               0 :     psFile = (AVCBinFile*)CPLCalloc(1, sizeof(AVCBinFile));
     163                 : 
     164               0 :     psFile->eFileType = eType;
     165               0 :     psFile->nPrecision = nPrecision;
     166                 : 
     167               0 :     psFile->pszFilename = (char*)CPLMalloc((strlen(pszPath)+strlen(pszName)+1)*
     168                 :                                            sizeof(char));
     169               0 :     sprintf(psFile->pszFilename, "%s%s", pszPath, pszName);
     170                 : 
     171               0 :     psFile->eCoverType = eCoverType;
     172                 : 
     173                 :     /*-----------------------------------------------------------------
     174                 :      * PRJ files are text files... we won't use the AVCRawBin*()
     175                 :      * functions for them... the file will be created and closed
     176                 :      * inside AVCBinWritePrj().
     177                 :      *----------------------------------------------------------------*/
     178               0 :     if (eType == AVCFilePRJ)
     179                 :     {
     180               0 :         return psFile;
     181                 :     }
     182                 : 
     183                 :     /*-----------------------------------------------------------------
     184                 :      * All other file types share a very similar creation method.
     185                 :      *----------------------------------------------------------------*/
     186               0 :     psFile->psRawBinFile = AVCRawBinOpen(psFile->pszFilename, "w",
     187               0 :                                  AVC_COVER_BYTE_ORDER(psFile->eCoverType),
     188                 :                                          psDBCSInfo);
     189                 : 
     190               0 :     if (psFile->psRawBinFile == NULL)
     191                 :     {
     192                 :         /* Failed to open file... just return NULL since an error message
     193                 :          * has already been issued by AVCRawBinOpen()
     194                 :          */
     195               0 :         CPLFree(psFile->pszFilename);
     196               0 :         CPLFree(psFile);
     197               0 :         return NULL;
     198                 :     }
     199                 : 
     200                 :     /*-----------------------------------------------------------------
     201                 :      * Create an Index file if applicable for current file type.
     202                 :      * Yep, we'll have a problem if filenames come in as uppercase, but
     203                 :      * this should not happen in a normal situation.
     204                 :      * For each type there is 3 possibilities, e.g. "pal", "pal.adf", "ttt.pal"
     205                 :      *----------------------------------------------------------------*/
     206               0 :     pszFname = CPLStrdup(psFile->pszFilename);
     207               0 :     nLen = strlen(pszFname);
     208               0 :     if (eType == AVCFileARC &&
     209               0 :         ( (nLen>=3 && EQUALN((pszExt=pszFname+nLen-3), "arc", 3)) ||
     210               0 :           (nLen>=7 && EQUALN((pszExt=pszFname+nLen-7), "arc.adf", 7)) ) )
     211                 :     {
     212               0 :         strncpy(pszExt, "arx", 3);
     213               0 :         bCreateIndex = TRUE;
     214                 :     }
     215               0 :     else if ((eType == AVCFilePAL || eType == AVCFileRPL) &&
     216               0 :              ( (nLen>=3 && EQUALN((pszExt=pszFname+nLen-3), "pal", 3)) ||
     217               0 :                (nLen>=7 && EQUALN((pszExt=pszFname+nLen-7), "pal.adf", 7)) ) )
     218                 :     {
     219               0 :         strncpy(pszExt, "pax", 3);
     220               0 :         bCreateIndex = TRUE;
     221                 :     }
     222               0 :     else if (eType == AVCFileCNT &&
     223               0 :              ( (nLen>=3 && EQUALN((pszExt=pszFname+nLen-3), "cnt", 3)) ||
     224               0 :                (nLen>=7 && EQUALN((pszExt=pszFname+nLen-7), "cnt.adf", 7)) ) )
     225                 :     {
     226               0 :         strncpy(pszExt, "cnx", 3);
     227               0 :         bCreateIndex = TRUE;
     228                 :     }
     229               0 :     else if ((eType == AVCFileTXT || eType == AVCFileTX6) &&
     230               0 :              ( (nLen>=3 && EQUALN((pszExt=pszFname+nLen-3), "txt", 3)) ||
     231               0 :                (nLen>=7 && EQUALN((pszExt=pszFname+nLen-7), "txt.adf", 7)) ) )
     232                 :     {
     233               0 :         strncpy(pszExt, "txx", 3);
     234               0 :         bCreateIndex = TRUE;
     235                 :     }
     236                 : 
     237               0 :     if (bCreateIndex)
     238                 :     {
     239               0 :         psFile->psIndexFile = AVCRawBinOpen(pszFname, "w",
     240               0 :                                     AVC_COVER_BYTE_ORDER(psFile->eCoverType),
     241                 :                                             psDBCSInfo);
     242                 :     }
     243                 : 
     244               0 :     CPLFree(pszFname);
     245                 : 
     246                 :     /*-----------------------------------------------------------------
     247                 :      * Generate the appropriate headers for the main file and its index
     248                 :      * if one was created.
     249                 :      *----------------------------------------------------------------*/
     250               0 :     if (AVCBinWriteHeader(psFile) == -1)
     251                 :     {
     252                 :         /* Failed!  Return NULL */
     253               0 :         AVCBinWriteClose(psFile);
     254               0 :         psFile = NULL;
     255                 :     }
     256                 : 
     257               0 :     return psFile;
     258                 : }
     259                 : 
     260                 : 
     261                 : /**********************************************************************
     262                 :  *                          _AVCBinWriteHeader()
     263                 :  *
     264                 :  * (This function is for internal library use... external calls should
     265                 :  * go to AVCBinWriteHeader() instead)
     266                 :  *
     267                 :  * Generate a 100 bytes header using the info in psHeader.
     268                 :  *
     269                 :  * Note: PC Coverage files have an initial 256 bytes header followed by the
     270                 :  * regular 100 bytes header.
     271                 :  *
     272                 :  * This function assumes that the file pointer is currently located at
     273                 :  * the beginning of the file.
     274                 :  *
     275                 :  * Returns 0 on success or -1 on error.
     276                 :  **********************************************************************/
     277               0 : int _AVCBinWriteHeader(AVCRawBinFile *psFile, AVCBinHeader *psHeader,
     278                 :                        AVCCoverType eCoverType)
     279                 : {
     280               0 :     int nStatus = 0;
     281                 : 
     282               0 :     if (eCoverType == AVCCoverPC)
     283                 :     {
     284                 :         /* PC Coverage header starts with an initial 256 bytes header
     285                 :          */
     286               0 :         AVCRawBinWriteInt16(psFile, 0x0400);  /* Signature??? */
     287               0 :         AVCRawBinWriteInt32(psFile, psHeader->nLength);
     288                 : 
     289               0 :         AVCRawBinWriteZeros(psFile, 250);
     290                 :     }
     291                 : 
     292               0 :     AVCRawBinWriteInt32(psFile, psHeader->nSignature);
     293               0 :     AVCRawBinWriteInt32(psFile, psHeader->nPrecision);
     294               0 :     AVCRawBinWriteInt32(psFile, psHeader->nRecordSize);
     295               0 :     AVCRawBinWriteZeros(psFile, 12);
     296               0 :     AVCRawBinWriteInt32(psFile, psHeader->nLength);
     297                 : 
     298                 :     /* Pad the rest of the header with zeros
     299                 :      */
     300               0 :     AVCRawBinWriteZeros(psFile, 72);
     301                 : 
     302               0 :     if (CPLGetLastErrorNo() != 0)
     303               0 :         nStatus = -1;
     304                 : 
     305               0 :     return nStatus;
     306                 : }
     307                 : 
     308                 : 
     309                 : /**********************************************************************
     310                 :  *                          AVCBinWriteHeader()
     311                 :  *
     312                 :  * Write a header to the specified file using the values that apply to
     313                 :  * this file's type.  The function simply does nothing if it is called
     314                 :  * for a file type that requires no header.
     315                 :  *
     316                 :  * Returns 0 on success or -1 on error.
     317                 :  **********************************************************************/
     318               0 : int AVCBinWriteHeader(AVCBinFile *psFile)
     319                 : {
     320                 :     AVCBinHeader sHeader;
     321               0 :     int          nStatus=0;
     322               0 :     GBool        bHeader = TRUE;
     323                 : 
     324                 :     /*-----------------------------------------------------------------
     325                 :      * Set the appropriate header information for this file type.
     326                 :      *----------------------------------------------------------------*/
     327               0 :     sHeader.nPrecision = sHeader.nRecordSize = sHeader.nLength = 0;
     328               0 :     sHeader.nSignature = 9994;
     329               0 :     switch(psFile->eFileType)
     330                 :     {
     331                 :       case AVCFileARC:
     332               0 :         sHeader.nPrecision = (psFile->nPrecision == AVC_DOUBLE_PREC)? -1 : 1;
     333               0 :         break;
     334                 :       case AVCFilePAL:
     335                 :       case AVCFileRPL:
     336               0 :         sHeader.nPrecision = (psFile->nPrecision == AVC_DOUBLE_PREC)? -11 : 11;
     337               0 :         break;
     338                 :       case AVCFileLAB:
     339               0 :         sHeader.nSignature = 9993;
     340               0 :         sHeader.nPrecision = (psFile->nPrecision == AVC_DOUBLE_PREC)? -2 : 2;
     341               0 :         sHeader.nRecordSize = (psFile->nPrecision == AVC_DOUBLE_PREC)? 28 : 16;
     342               0 :         break;
     343                 :       case AVCFileCNT:
     344               0 :         sHeader.nPrecision = (psFile->nPrecision == AVC_DOUBLE_PREC)? -14 : 14;
     345               0 :         break;
     346                 :       case AVCFileTOL:
     347                 :         /* single prec: tol.adf has no header
     348                 :          * double prec: par.adf has a header
     349                 :          */
     350               0 :         if (psFile->nPrecision == AVC_DOUBLE_PREC)
     351                 :         {
     352               0 :             sHeader.nSignature = 9993;
     353               0 :             sHeader.nPrecision = 40;
     354               0 :             sHeader.nRecordSize = 8;
     355                 :         }
     356                 :         else
     357                 :         {
     358               0 :             bHeader = FALSE;
     359                 :         }
     360               0 :         break;
     361                 :       case AVCFileTXT:
     362                 :       case AVCFileTX6:
     363               0 :         if (psFile->eCoverType == AVCCoverPC)
     364               0 :             sHeader.nPrecision = 1;
     365                 :         else
     366               0 :             sHeader.nPrecision = (psFile->nPrecision==AVC_DOUBLE_PREC)? -67:67;
     367               0 :         break;
     368                 :       default:
     369                 :         /* Other file types don't need a header */
     370               0 :         bHeader = FALSE;
     371                 :     }
     372                 : 
     373                 :     /*-----------------------------------------------------------------
     374                 :      * Write a header only if applicable.
     375                 :      *----------------------------------------------------------------*/
     376               0 :     if (bHeader)
     377               0 :         nStatus = _AVCBinWriteHeader(psFile->psRawBinFile, &sHeader,
     378                 :                                      psFile->eCoverType);
     379                 : 
     380                 :     /*-----------------------------------------------------------------
     381                 :      * Write a header for the index file... it is identical to the main
     382                 :      * file's header.
     383                 :      *----------------------------------------------------------------*/
     384               0 :     if (nStatus == 0 && bHeader && psFile->psIndexFile)
     385               0 :         nStatus = _AVCBinWriteHeader(psFile->psIndexFile, &sHeader,
     386                 :                                      psFile->eCoverType);
     387                 : 
     388               0 :     return nStatus;
     389                 : }
     390                 : 
     391                 : /**********************************************************************
     392                 :  *                          AVCBinWriteClose()
     393                 :  *
     394                 :  * Close a coverage file opened for wirting, and release all memory 
     395                 :  * (object strcut., buffers, etc.) associated with this file.
     396                 :  **********************************************************************/
     397                 : 
     398               0 : void    AVCBinWriteClose(AVCBinFile *psFile)
     399                 : {
     400               0 :     if (psFile->eFileType == AVCFileTABLE)
     401                 :     {
     402               0 :         _AVCBinWriteCloseTable(psFile);
     403               0 :         return;
     404                 :     }
     405                 : 
     406                 :     /*-----------------------------------------------------------------
     407                 :      * Write the file size (nbr of 2 byte words) in the header at 
     408                 :      * byte 24 in the 100 byte header (only if applicable)
     409                 :      * (And write the same value at byte 2-5 in the first header of PC Cover)
     410                 :      *----------------------------------------------------------------*/
     411               0 :     if (psFile->psRawBinFile &&
     412               0 :         (psFile->eFileType == AVCFileARC ||
     413               0 :          psFile->eFileType == AVCFilePAL ||
     414               0 :          psFile->eFileType == AVCFileRPL ||
     415               0 :          psFile->eFileType == AVCFileLAB ||
     416               0 :          psFile->eFileType == AVCFileCNT ||
     417               0 :          psFile->eFileType == AVCFileTXT ||
     418               0 :          psFile->eFileType == AVCFileTX6 ||
     419               0 :          (psFile->eFileType == AVCFileTOL && 
     420               0 :           psFile->nPrecision == AVC_DOUBLE_PREC) ) )
     421                 :     {
     422                 :         GInt32 n32Size;
     423               0 :         n32Size = psFile->psRawBinFile->nCurPos/2;
     424                 : 
     425               0 :         if (psFile->eCoverType == AVCCoverPC)
     426                 :         {
     427                 :             /* PC Cover... Pad to multiple of 512 bytes and write 2 headers
     428                 :              * extra bytes at EOF are not included in the size written in
     429                 :              * header.
     430                 :              * The first 256 bytes header is not counted in the file size 
     431                 :              * written in both headers
     432                 :              */
     433               0 :             n32Size -= 128;  /* minus 256 bytes */
     434                 : 
     435               0 :             if (psFile->psRawBinFile->nCurPos%512 != 0)
     436               0 :                 AVCRawBinWriteZeros(psFile->psRawBinFile, 
     437               0 :                                     512 - psFile->psRawBinFile->nCurPos%512);
     438                 :                 
     439               0 :             VSIFSeek(psFile->psRawBinFile->fp, 2, SEEK_SET);
     440               0 :             AVCRawBinWriteInt32(psFile->psRawBinFile, n32Size);
     441                 : 
     442               0 :             VSIFSeek(psFile->psRawBinFile->fp, 256+24, SEEK_SET);
     443               0 :             AVCRawBinWriteInt32(psFile->psRawBinFile, n32Size);
     444                 :         }
     445                 :         else
     446                 :         {
     447                 :             /* V7 Cover ... only 1 header */
     448               0 :             VSIFSeek(psFile->psRawBinFile->fp, 24, SEEK_SET);
     449               0 :             AVCRawBinWriteInt32(psFile->psRawBinFile, n32Size);
     450                 :         }
     451                 :     }
     452                 :         
     453               0 :     AVCRawBinClose(psFile->psRawBinFile);
     454               0 :     psFile->psRawBinFile = NULL;
     455                 : 
     456                 :     /*-----------------------------------------------------------------
     457                 :      * Same for the index file if it exists.
     458                 :      *----------------------------------------------------------------*/
     459               0 :     if (psFile->psIndexFile)
     460                 :     {
     461                 :         GInt32 n32Size;
     462               0 :         n32Size = psFile->psIndexFile->nCurPos/2;
     463                 : 
     464               0 :         if (psFile->eCoverType == AVCCoverPC)
     465                 :         {
     466                 :             /* PC Cover... Pad to multiple of 512 bytes and write 2 headers
     467                 :              * extra bytes at EOF are not included in the size written in
     468                 :              * header
     469                 :              */
     470               0 :             n32Size -= 128;  /* minus 256 bytes */
     471                 : 
     472               0 :             if (psFile->psIndexFile->nCurPos%512 != 0)
     473               0 :                 AVCRawBinWriteZeros(psFile->psIndexFile, 
     474               0 :                                     512 - psFile->psIndexFile->nCurPos%512);
     475                 :                 
     476               0 :             VSIFSeek(psFile->psIndexFile->fp, 2, SEEK_SET);
     477               0 :             AVCRawBinWriteInt32(psFile->psIndexFile, n32Size);
     478                 : 
     479               0 :             VSIFSeek(psFile->psIndexFile->fp, 256+24, SEEK_SET);
     480               0 :             AVCRawBinWriteInt32(psFile->psIndexFile, n32Size);
     481                 :         }
     482                 :         else
     483                 :         {
     484                 :             /* V7 Cover ... only 1 header */
     485               0 :             VSIFSeek(psFile->psIndexFile->fp, 24, SEEK_SET);
     486               0 :             AVCRawBinWriteInt32(psFile->psIndexFile, n32Size);
     487                 :         }
     488                 : 
     489               0 :         AVCRawBinClose(psFile->psIndexFile);
     490               0 :         psFile->psIndexFile = NULL;
     491                 :     }
     492                 : 
     493               0 :     CPLFree(psFile->pszFilename);
     494                 : 
     495               0 :     CPLFree(psFile);
     496                 : }
     497                 : 
     498                 : 
     499                 : 
     500                 : /**********************************************************************
     501                 :  *                          _AVCBinWriteIndexEntry()
     502                 :  *
     503                 :  * (This function is for internal library use... the index entries
     504                 :  * are automatically handled by the AVCBinWrite*() functions)
     505                 :  *
     506                 :  * Write an Index Entry at the current position in the file.
     507                 :  *
     508                 :  * Position is relative to the beginning of the file, including the header.
     509                 :  * Both position and size are specified in number of 2 byte words.
     510                 :  *
     511                 :  * Returns 0 on success or -1 on error.
     512                 :  **********************************************************************/
     513               0 : int _AVCBinWriteIndexEntry(AVCRawBinFile *psFile, 
     514                 :                            int nPosition, int nSize)
     515                 : {
     516               0 :     AVCRawBinWriteInt32(psFile, nPosition);
     517               0 :     AVCRawBinWriteInt32(psFile, nSize);
     518                 : 
     519               0 :     if (CPLGetLastErrorNo() != 0)
     520               0 :         return -1;
     521                 : 
     522               0 :     return 0;
     523                 : }
     524                 : 
     525                 : /**********************************************************************
     526                 :  *                          AVCBinWriteObject()
     527                 :  *
     528                 :  * Write a CNT (Polygon Centroid) structure to the fin object to a 
     529                 :  * coverage file.
     530                 :  *
     531                 :  * Simply redirects the call to the right function based on the value
     532                 :  * of psFile->eFileType.
     533                 :  *
     534                 :  * Returns 0 on success or -1 on error.
     535                 :  *
     536                 :  * If a problem happens, then CPLError() will be called by the lower-level
     537                 :  * functions and CPLGetLastErrorNo() can be used to find out what happened.
     538                 :  **********************************************************************/
     539               0 : int AVCBinWriteObject(AVCBinFile *psFile, void *psObj)
     540                 : {
     541               0 :     int nStatus = 0;
     542               0 :     switch(psFile->eFileType)
     543                 :     {
     544                 :       case AVCFileARC:
     545               0 :         nStatus = AVCBinWriteArc(psFile, (AVCArc *)psObj);
     546               0 :         break;
     547                 :       case AVCFilePAL:
     548                 :       case AVCFileRPL:
     549               0 :         nStatus = AVCBinWritePal(psFile, (AVCPal *)psObj);
     550               0 :         break;
     551                 :       case AVCFileCNT:
     552               0 :         nStatus = AVCBinWriteCnt(psFile, (AVCCnt *)psObj);
     553               0 :         break;
     554                 :       case AVCFileLAB:
     555               0 :         nStatus = AVCBinWriteLab(psFile, (AVCLab *)psObj);
     556               0 :         break;
     557                 :       case AVCFileTOL:
     558               0 :         nStatus = AVCBinWriteTol(psFile, (AVCTol *)psObj);
     559               0 :         break;
     560                 :       case AVCFilePRJ:
     561               0 :         nStatus = AVCBinWritePrj(psFile, (char **)psObj);
     562               0 :         break;
     563                 :       case AVCFileTXT:
     564                 :       case AVCFileTX6:
     565               0 :         nStatus = AVCBinWriteTxt(psFile, (AVCTxt *)psObj);
     566               0 :         break;
     567                 :       case AVCFileRXP:
     568               0 :         nStatus = AVCBinWriteRxp(psFile, (AVCRxp *)psObj);
     569               0 :         break;
     570                 :       case AVCFileTABLE:
     571               0 :         nStatus = AVCBinWriteTableRec(psFile, (AVCField *)psObj);
     572               0 :         break;
     573                 :       default:
     574               0 :         CPLError(CE_Failure, CPLE_IllegalArg,
     575                 :                  "AVCBinWriteObject(): Unsupported file type!");
     576               0 :         nStatus = -1;
     577                 :     }
     578                 : 
     579               0 :     return nStatus;
     580                 : }
     581                 : 
     582                 : 
     583                 : /*=====================================================================
     584                 :  *                              ARC
     585                 :  *====================================================================*/
     586                 : 
     587                 : /**********************************************************************
     588                 :  *                          _AVCBinWriteArc()
     589                 :  *
     590                 :  * (This function is for internal library use... external calls should
     591                 :  * go to AVCBinWriteNextArc() instead)
     592                 :  *
     593                 :  * Write an Arc structure to the file.
     594                 :  *
     595                 :  * The contents of the psArc structure is assumed to be valid... this
     596                 :  * function performs no validation on the consistency of what it is 
     597                 :  * given as input.
     598                 :  *
     599                 :  * Returns 0 on success or -1 on error.
     600                 :  **********************************************************************/
     601               0 : int _AVCBinWriteArc(AVCRawBinFile *psFile, AVCArc *psArc,
     602                 :                     int nPrecision, AVCRawBinFile *psIndexFile)
     603                 : {
     604                 :     int         i, nRecSize, nCurPos;
     605                 : 
     606               0 :     nCurPos = psFile->nCurPos/2;  /* Value in 2 byte words */
     607                 : 
     608               0 :     AVCRawBinWriteInt32(psFile, psArc->nArcId);
     609               0 :     if (CPLGetLastErrorNo() != 0)
     610               0 :         return -1;
     611                 : 
     612                 :     /*-----------------------------------------------------------------
     613                 :      * Record size is expressed in 2 byte words, and does not count the
     614                 :      * first 8 bytes of the ARC entry.
     615                 :      *----------------------------------------------------------------*/
     616               0 :     nRecSize = (6 * 4 + psArc->numVertices*2 * 
     617                 :                 ((nPrecision == AVC_SINGLE_PREC)? 4 : 8)) / 2;
     618               0 :     AVCRawBinWriteInt32(psFile, nRecSize);
     619               0 :     AVCRawBinWriteInt32(psFile, psArc->nUserId);
     620               0 :     AVCRawBinWriteInt32(psFile, psArc->nFNode);
     621               0 :     AVCRawBinWriteInt32(psFile, psArc->nTNode);
     622               0 :     AVCRawBinWriteInt32(psFile, psArc->nLPoly);
     623               0 :     AVCRawBinWriteInt32(psFile, psArc->nRPoly);
     624               0 :     AVCRawBinWriteInt32(psFile, psArc->numVertices);
     625                 : 
     626               0 :     if (nPrecision == AVC_SINGLE_PREC)
     627                 :     {
     628               0 :         for(i=0; i<psArc->numVertices; i++)
     629                 :         {
     630               0 :             AVCRawBinWriteFloat(psFile, (float)psArc->pasVertices[i].x);
     631               0 :             AVCRawBinWriteFloat(psFile, (float)psArc->pasVertices[i].y);
     632                 :         }
     633                 :     }
     634                 :     else
     635                 :     {
     636               0 :         for(i=0; i<psArc->numVertices; i++)
     637                 :         {
     638               0 :             AVCRawBinWriteDouble(psFile, psArc->pasVertices[i].x);
     639               0 :             AVCRawBinWriteDouble(psFile, psArc->pasVertices[i].y);
     640                 :         }
     641                 : 
     642                 :     }
     643                 : 
     644                 :     /*-----------------------------------------------------------------
     645                 :      * Write index entry (arx.adf)
     646                 :      *----------------------------------------------------------------*/
     647               0 :     if (psIndexFile)
     648                 :     {
     649               0 :         _AVCBinWriteIndexEntry(psIndexFile, nCurPos, nRecSize);
     650                 :     }
     651                 : 
     652               0 :     if (CPLGetLastErrorNo() != 0)
     653               0 :         return -1;
     654                 : 
     655               0 :     return 0;
     656                 : }
     657                 : 
     658                 : /**********************************************************************
     659                 :  *                          AVCBinWriteArc()
     660                 :  *
     661                 :  * Write the next Arc structure to the file.
     662                 :  *
     663                 :  * The contents of the psArc structure is assumed to be valid... this
     664                 :  * function performs no validation on the consistency of what it is 
     665                 :  * given as input.
     666                 :  *
     667                 :  * Returns 0 on success or -1 on error.
     668                 :  *
     669                 :  * If a problem happens, then CPLError() will be called by the lower-level
     670                 :  * functions and CPLGetLastErrorNo() can be used to find out what happened.
     671                 :  **********************************************************************/
     672               0 : int AVCBinWriteArc(AVCBinFile *psFile, AVCArc *psArc)
     673                 : {
     674               0 :     if (psFile->eFileType != AVCFileARC)
     675               0 :         return -1;
     676                 : 
     677               0 :     return _AVCBinWriteArc(psFile->psRawBinFile, psArc,
     678                 :                            psFile->nPrecision, psFile->psIndexFile);
     679                 : }
     680                 : 
     681                 : 
     682                 : /*=====================================================================
     683                 :  *                              PAL
     684                 :  *====================================================================*/
     685                 : 
     686                 : /**********************************************************************
     687                 :  *                          _AVCBinWritePal()
     688                 :  *
     689                 :  * (This function is for internal library use... external calls should
     690                 :  * go to AVCBinWritePal() instead)
     691                 :  *
     692                 :  * Write a PAL (Polygon Arc List) structure to the file.
     693                 :  *
     694                 :  * The contents of the psPal structure is assumed to be valid... this
     695                 :  * function performs no validation on the consistency of what it is 
     696                 :  * given as input.
     697                 :  *
     698                 :  * Returns 0 on success or -1 on error.
     699                 :  **********************************************************************/
     700               0 : int _AVCBinWritePal(AVCRawBinFile *psFile, AVCPal *psPal, 
     701                 :                     int nPrecision, AVCRawBinFile *psIndexFile)
     702                 : {
     703                 :     int i, nRecSize, nCurPos;
     704                 : 
     705               0 :     nCurPos = psFile->nCurPos/2;  /* Value in 2 byte words */
     706                 : 
     707               0 :     AVCRawBinWriteInt32(psFile, psPal->nPolyId);
     708               0 :     if (CPLGetLastErrorNo() != 0)
     709               0 :         return -1;
     710                 : 
     711                 :     /*-----------------------------------------------------------------
     712                 :      * Record size is expressed in 2 byte words, and does not count the
     713                 :      * first 8 bytes of the PAL entry.
     714                 :      *----------------------------------------------------------------*/
     715               0 :     nRecSize = ( 4 + psPal->numArcs*3 * 4 + 
     716               0 :                 4 * ((nPrecision == AVC_SINGLE_PREC)? 4 : 8)) / 2;
     717                 : 
     718               0 :     AVCRawBinWriteInt32(psFile, nRecSize);
     719                 : 
     720               0 :     if (nPrecision == AVC_SINGLE_PREC)
     721                 :     {
     722               0 :         AVCRawBinWriteFloat(psFile, (float)psPal->sMin.x);
     723               0 :         AVCRawBinWriteFloat(psFile, (float)psPal->sMin.y);
     724               0 :         AVCRawBinWriteFloat(psFile, (float)psPal->sMax.x);
     725               0 :         AVCRawBinWriteFloat(psFile, (float)psPal->sMax.y);
     726                 :     }
     727                 :     else
     728                 :     {
     729               0 :         AVCRawBinWriteDouble(psFile, psPal->sMin.x);
     730               0 :         AVCRawBinWriteDouble(psFile, psPal->sMin.y);
     731               0 :         AVCRawBinWriteDouble(psFile, psPal->sMax.x);
     732               0 :         AVCRawBinWriteDouble(psFile, psPal->sMax.y);
     733                 :     }
     734                 : 
     735               0 :     AVCRawBinWriteInt32(psFile, psPal->numArcs);
     736                 : 
     737               0 :     for(i=0; i<psPal->numArcs; i++)
     738                 :     {
     739               0 :         AVCRawBinWriteInt32(psFile, psPal->pasArcs[i].nArcId);
     740               0 :         AVCRawBinWriteInt32(psFile, psPal->pasArcs[i].nFNode);
     741               0 :         AVCRawBinWriteInt32(psFile, psPal->pasArcs[i].nAdjPoly);
     742                 :     }
     743                 : 
     744                 :     /*-----------------------------------------------------------------
     745                 :      * Write index entry (pax.adf)
     746                 :      *----------------------------------------------------------------*/
     747               0 :     if (psIndexFile)
     748                 :     {
     749               0 :         _AVCBinWriteIndexEntry(psIndexFile, nCurPos, nRecSize);
     750                 :     }
     751                 : 
     752               0 :     if (CPLGetLastErrorNo() != 0)
     753               0 :         return -1;
     754                 : 
     755               0 :     return 0;
     756                 : }
     757                 : 
     758                 : /**********************************************************************
     759                 :  *                          AVCBinWritePal()
     760                 :  *
     761                 :  * Write a PAL (Polygon Arc List) structure to the file.
     762                 :  *
     763                 :  * The contents of the psPal structure is assumed to be valid... this
     764                 :  * function performs no validation on the consistency of what it is 
     765                 :  * given as input.
     766                 :  *
     767                 :  * Returns 0 on success or -1 on error.
     768                 :  *
     769                 :  * If a problem happens, then CPLError() will be called by the lower-level
     770                 :  * functions and CPLGetLastErrorNo() can be used to find out what happened.
     771                 :  **********************************************************************/
     772               0 : int AVCBinWritePal(AVCBinFile *psFile, AVCPal *psPal)
     773                 : {
     774               0 :     if (psFile->eFileType != AVCFilePAL && psFile->eFileType != AVCFileRPL)
     775               0 :         return -1;
     776                 : 
     777               0 :     return _AVCBinWritePal(psFile->psRawBinFile, psPal,
     778                 :                            psFile->nPrecision, psFile->psIndexFile);
     779                 : }
     780                 : 
     781                 : /*=====================================================================
     782                 :  *                              CNT
     783                 :  *====================================================================*/
     784                 : 
     785                 : /**********************************************************************
     786                 :  *                          _AVCBinWriteCnt()
     787                 :  *
     788                 :  * (This function is for internal library use... external calls should
     789                 :  * go to AVCBinWriteCnt() instead)
     790                 :  *
     791                 :  * Write a CNT (Polygon Centroid) structure to the file.
     792                 :  *
     793                 :  * Returns 0 on success or -1 on error.
     794                 :  **********************************************************************/
     795               0 : int _AVCBinWriteCnt(AVCRawBinFile *psFile, AVCCnt *psCnt, 
     796                 :                               int nPrecision, AVCRawBinFile *psIndexFile)
     797                 : {
     798                 :     int i, nRecSize, nCurPos;
     799                 : 
     800               0 :     nCurPos = psFile->nCurPos/2;  /* Value in 2 byte words */
     801                 : 
     802               0 :     AVCRawBinWriteInt32(psFile, psCnt->nPolyId);
     803               0 :     if (CPLGetLastErrorNo() != 0)
     804               0 :         return -1;
     805                 : 
     806                 :     /*-----------------------------------------------------------------
     807                 :      * Record size is expressed in 2 byte words, and does not count the
     808                 :      * first 8 bytes of the CNT entry.
     809                 :      *----------------------------------------------------------------*/
     810               0 :     nRecSize = ( 4 + psCnt->numLabels * 4 + 
     811               0 :                  2 * ((nPrecision == AVC_SINGLE_PREC)? 4 : 8)) / 2;
     812                 : 
     813               0 :     AVCRawBinWriteInt32(psFile, nRecSize);
     814                 : 
     815               0 :     if (nPrecision == AVC_SINGLE_PREC)
     816                 :     {
     817               0 :         AVCRawBinWriteFloat(psFile, (float)psCnt->sCoord.x);
     818               0 :         AVCRawBinWriteFloat(psFile, (float)psCnt->sCoord.y);
     819                 :     }
     820                 :     else
     821                 :     {
     822               0 :         AVCRawBinWriteDouble(psFile, psCnt->sCoord.x);
     823               0 :         AVCRawBinWriteDouble(psFile, psCnt->sCoord.y);
     824                 :     }
     825                 : 
     826               0 :     AVCRawBinWriteInt32(psFile, psCnt->numLabels);
     827                 : 
     828               0 :     for(i=0; i<psCnt->numLabels; i++)
     829                 :     {
     830               0 :         AVCRawBinWriteInt32(psFile, psCnt->panLabelIds[i]);
     831                 :     }
     832                 : 
     833                 :     /*-----------------------------------------------------------------
     834                 :      * Write index entry (cnx.adf)
     835                 :      *----------------------------------------------------------------*/
     836               0 :     if (psIndexFile)
     837                 :     {
     838               0 :         _AVCBinWriteIndexEntry(psIndexFile, nCurPos, nRecSize);
     839                 :     }
     840                 : 
     841               0 :     if (CPLGetLastErrorNo() != 0)
     842               0 :         return -1;
     843                 : 
     844               0 :     return 0;
     845                 : }
     846                 : 
     847                 : /**********************************************************************
     848                 :  *                          AVCBinWriteCnt()
     849                 :  *
     850                 :  * Write a CNT (Polygon Centroid) structure to the file.
     851                 :  *
     852                 :  * The contents of the psCnt structure is assumed to be valid... this
     853                 :  * function performs no validation on the consistency of what it is 
     854                 :  * given as input.
     855                 :  *
     856                 :  * Returns 0 on success or -1 on error.
     857                 :  *
     858                 :  * If a problem happens, then CPLError() will be called by the lower-level
     859                 :  * functions and CPLGetLastErrorNo() can be used to find out what happened.
     860                 :  **********************************************************************/
     861               0 : int AVCBinWriteCnt(AVCBinFile *psFile, AVCCnt *psCnt)
     862                 : {
     863               0 :     if (psFile->eFileType != AVCFileCNT)
     864               0 :         return -1;
     865                 : 
     866               0 :     return _AVCBinWriteCnt(psFile->psRawBinFile, psCnt,
     867                 :                            psFile->nPrecision, psFile->psIndexFile);
     868                 : }
     869                 : 
     870                 : /*=====================================================================
     871                 :  *                              LAB
     872                 :  *====================================================================*/
     873                 : 
     874                 : /**********************************************************************
     875                 :  *                          _AVCBinWriteLab()
     876                 :  *
     877                 :  * (This function is for internal library use... external calls should
     878                 :  * go to AVCBinWriteLab() instead)
     879                 :  *
     880                 :  * Write a LAB (Centroid Label) structure to the file.
     881                 :  *
     882                 :  * The contents of the psLab structure is assumed to be valid... this
     883                 :  * function performs no validation on the consistency of what it is 
     884                 :  * given as input.
     885                 :  *
     886                 :  * Returns 0 on success or -1 on error.
     887                 :  **********************************************************************/
     888               0 : int _AVCBinWriteLab(AVCRawBinFile *psFile, AVCLab *psLab, 
     889                 :                     int nPrecision)
     890                 : {
     891                 : 
     892               0 :     AVCRawBinWriteInt32(psFile, psLab->nValue);
     893               0 :     if (CPLGetLastErrorNo() != 0)
     894               0 :         return -1;
     895                 : 
     896               0 :     AVCRawBinWriteInt32(psFile, psLab->nPolyId);
     897                 : 
     898               0 :     if (nPrecision == AVC_SINGLE_PREC)
     899                 :     {
     900               0 :         AVCRawBinWriteFloat(psFile, (float)psLab->sCoord1.x);
     901               0 :         AVCRawBinWriteFloat(psFile, (float)psLab->sCoord1.y);
     902               0 :         AVCRawBinWriteFloat(psFile, (float)psLab->sCoord2.x);
     903               0 :         AVCRawBinWriteFloat(psFile, (float)psLab->sCoord2.y);
     904               0 :         AVCRawBinWriteFloat(psFile, (float)psLab->sCoord3.x);
     905               0 :         AVCRawBinWriteFloat(psFile, (float)psLab->sCoord3.y);
     906                 :     }
     907                 :     else
     908                 :     {
     909               0 :         AVCRawBinWriteDouble(psFile, psLab->sCoord1.x);
     910               0 :         AVCRawBinWriteDouble(psFile, psLab->sCoord1.y);
     911               0 :         AVCRawBinWriteDouble(psFile, psLab->sCoord2.x);
     912               0 :         AVCRawBinWriteDouble(psFile, psLab->sCoord2.y);
     913               0 :         AVCRawBinWriteDouble(psFile, psLab->sCoord3.x);
     914               0 :         AVCRawBinWriteDouble(psFile, psLab->sCoord3.y);
     915                 :     }
     916                 : 
     917               0 :     if (CPLGetLastErrorNo() != 0)
     918               0 :         return -1;
     919                 : 
     920               0 :     return 0;
     921                 : }
     922                 : 
     923                 : 
     924                 : /**********************************************************************
     925                 :  *                          AVCBinWriteLab()
     926                 :  *
     927                 :  * Write a LAB (Centroid Label) structure to the file.
     928                 :  *
     929                 :  * The contents of the psLab structure is assumed to be valid... this
     930                 :  * function performs no validation on the consistency of what it is 
     931                 :  * given as input.
     932                 :  *
     933                 :  * Returns 0 on success or -1 on error.
     934                 :  *
     935                 :  * If a problem happens, then CPLError() will be called by the lower-level
     936                 :  * functions and CPLGetLastErrorNo() can be used to find out what happened.
     937                 :  **********************************************************************/
     938               0 : int AVCBinWriteLab(AVCBinFile *psFile, AVCLab *psLab)
     939                 : {
     940               0 :     if (psFile->eFileType != AVCFileLAB)
     941               0 :         return -1;
     942                 : 
     943               0 :     return _AVCBinWriteLab(psFile->psRawBinFile, psLab,
     944                 :                            psFile->nPrecision);
     945                 : }
     946                 : 
     947                 : /*=====================================================================
     948                 :  *                              TOL
     949                 :  *====================================================================*/
     950                 : 
     951                 : /**********************************************************************
     952                 :  *                          _AVCBinWriteTol()
     953                 :  *
     954                 :  * (This function is for internal library use... external calls should
     955                 :  * go to AVCBinWriteTol() instead)
     956                 :  *
     957                 :  * Write a TOL (tolerance) structure to the file.
     958                 :  *
     959                 :  * The contents of the psTol structure is assumed to be valid... this
     960                 :  * function performs no validation on the consistency of what it is 
     961                 :  * given as input.
     962                 :  *
     963                 :  * Returns 0 on success or -1 on error.
     964                 :  **********************************************************************/
     965               0 : int _AVCBinWriteTol(AVCRawBinFile *psFile, AVCTol *psTol, 
     966                 :                     int nPrecision)
     967                 : {
     968                 : 
     969               0 :     AVCRawBinWriteInt32(psFile, psTol->nIndex);
     970               0 :     if (CPLGetLastErrorNo() != 0)
     971               0 :         return -1;
     972                 : 
     973               0 :     AVCRawBinWriteInt32(psFile, psTol->nFlag);
     974                 : 
     975               0 :     if (nPrecision == AVC_SINGLE_PREC)
     976                 :     {
     977               0 :         AVCRawBinWriteFloat(psFile, (float)psTol->dValue);
     978                 :     }
     979                 :     else
     980                 :     {
     981               0 :         AVCRawBinWriteDouble(psFile, psTol->dValue);
     982                 :     }
     983                 : 
     984               0 :     if (CPLGetLastErrorNo() != 0)
     985               0 :         return -1;
     986                 : 
     987               0 :     return 0;
     988                 : }
     989                 : 
     990                 : /**********************************************************************
     991                 :  *                          AVCBinWriteTol()
     992                 :  *
     993                 :  * Write a TOL (tolerance) structure to the file.
     994                 :  *
     995                 :  * The contents of the psTol structure is assumed to be valid... this
     996                 :  * function performs no validation on the consistency of what it is 
     997                 :  * given as input.
     998                 :  *
     999                 :  * Returns 0 on success or -1 on error.
    1000                 :  *
    1001                 :  * If a problem happens, then CPLError() will be called by the lower-level
    1002                 :  * functions and CPLGetLastErrorNo() can be used to find out what happened.
    1003                 :  **********************************************************************/
    1004               0 : int AVCBinWriteTol(AVCBinFile *psFile, AVCTol *psTol)
    1005                 : {
    1006               0 :     if (psFile->eFileType != AVCFileTOL)
    1007               0 :         return -1;
    1008                 : 
    1009               0 :     return _AVCBinWriteTol(psFile->psRawBinFile, psTol,
    1010                 :                            psFile->nPrecision);
    1011                 : }
    1012                 : 
    1013                 : /*=====================================================================
    1014                 :  *                              PRJ
    1015                 :  *====================================================================*/
    1016                 : 
    1017                 : /**********************************************************************
    1018                 :  *                          AVCBinWritePrj()
    1019                 :  *
    1020                 :  * Write a PRJ (Projection info) to the file.
    1021                 :  *
    1022                 :  * Since a PRJ file is a simple text file and there is only ONE projection
    1023                 :  * info per prj.adf file, this function behaves differently from the 
    1024                 :  * other ones... all the job is done here, including creating and closing
    1025                 :  * the output file.
    1026                 :  *
    1027                 :  * The contents of the papszPrj is assumed to be valid... this
    1028                 :  * function performs no validation on the consistency of what it is 
    1029                 :  * given as input.
    1030                 :  *
    1031                 :  * Returns 0 on success or -1 on error.
    1032                 :  *
    1033                 :  * If a problem happens, then CPLError() will be called by the lower-level
    1034                 :  * functions and CPLGetLastErrorNo() can be used to find out what happened.
    1035                 :  **********************************************************************/
    1036               0 : int AVCBinWritePrj(AVCBinFile *psFile, char **papszPrj)
    1037                 : {
    1038               0 :     if (psFile->eFileType != AVCFilePRJ)
    1039               0 :         return -1;
    1040                 : 
    1041               0 :     CSLSave(papszPrj, psFile->pszFilename);
    1042                 : 
    1043               0 :     if (CPLGetLastErrorNo() != 0)
    1044               0 :         return -1;
    1045                 : 
    1046               0 :     return 0;
    1047                 : }
    1048                 : 
    1049                 : 
    1050                 : /*=====================================================================
    1051                 :  *                              TXT/TX6/TX7
    1052                 :  *====================================================================*/
    1053                 : 
    1054                 : /**********************************************************************
    1055                 :  *                          _AVCBinWriteTxt()
    1056                 :  *
    1057                 :  * (This function is for internal library use... external calls should
    1058                 :  * go to AVCBinWriteTxt() instead)
    1059                 :  *
    1060                 :  * Write a TXT/TX6/TX7 (Annotation) structure to the file.
    1061                 :  *
    1062                 :  * The contents of the psTxt structure is assumed to be valid... this
    1063                 :  * function performs no validation on the consistency of what it is 
    1064                 :  * given as input.
    1065                 :  *
    1066                 :  * Returns 0 on success or -1 on error.
    1067                 :  **********************************************************************/
    1068               0 : int _AVCBinWriteTxt(AVCRawBinFile *psFile, AVCTxt *psTxt, 
    1069                 :                               int nPrecision, AVCRawBinFile *psIndexFile)
    1070                 : {
    1071                 :     int i, nRecSize, nCurPos, nStrLen, numVertices;
    1072                 : 
    1073               0 :     nCurPos = psFile->nCurPos/2;  /* Value in 2 byte words */
    1074                 : 
    1075               0 :     AVCRawBinWriteInt32(psFile, psTxt->nTxtId);
    1076               0 :     if (CPLGetLastErrorNo() != 0)
    1077               0 :         return -1;
    1078                 : 
    1079                 :     /*-----------------------------------------------------------------
    1080                 :      * Record size is expressed in 2 byte words, and does not count the
    1081                 :      * first 8 bytes of the TXT entry.
    1082                 :      *----------------------------------------------------------------*/
    1083                 :     /* String uses a multiple of 4 bytes of storage */
    1084               0 :     if (psTxt->pszText)
    1085               0 :         nStrLen = ((strlen((char*)psTxt->pszText) + 3)/4)*4;
    1086                 :     else
    1087               0 :         nStrLen = 0;
    1088                 : 
    1089               0 :     numVertices = ABS(psTxt->numVerticesLine) + ABS(psTxt->numVerticesArrow);
    1090               0 :     nRecSize = (112 + 8 + nStrLen + 
    1091               0 :                 (numVertices*2+3)* ((nPrecision == AVC_SINGLE_PREC)?4:8)) / 2;
    1092                 : 
    1093               0 :     AVCRawBinWriteInt32(psFile, nRecSize);
    1094                 : 
    1095               0 :     AVCRawBinWriteInt32(psFile, psTxt->nUserId );
    1096               0 :     AVCRawBinWriteInt32(psFile, psTxt->nLevel );
    1097               0 :     AVCRawBinWriteFloat(psFile, psTxt->f_1e2 );
    1098               0 :     AVCRawBinWriteInt32(psFile, psTxt->nSymbol );
    1099               0 :     AVCRawBinWriteInt32(psFile, psTxt->numVerticesLine );
    1100               0 :     AVCRawBinWriteInt32(psFile, psTxt->n28 );
    1101               0 :     AVCRawBinWriteInt32(psFile, psTxt->numChars );
    1102               0 :     AVCRawBinWriteInt32(psFile, psTxt->numVerticesArrow );
    1103                 : 
    1104               0 :     for(i=0; i<20; i++)
    1105                 :     {
    1106               0 :         AVCRawBinWriteInt16(psFile, psTxt->anJust1[i] );
    1107                 :     }
    1108               0 :     for(i=0; i<20; i++)
    1109                 :     {
    1110               0 :         AVCRawBinWriteInt16(psFile, psTxt->anJust2[i] );
    1111                 :     }
    1112                 : 
    1113               0 :     if (nPrecision == AVC_SINGLE_PREC)
    1114                 :     {
    1115               0 :         AVCRawBinWriteFloat(psFile, (float)psTxt->dHeight);
    1116               0 :         AVCRawBinWriteFloat(psFile, (float)psTxt->dV2);
    1117               0 :         AVCRawBinWriteFloat(psFile, (float)psTxt->dV3);
    1118                 :     }
    1119                 :     else
    1120                 :     {
    1121               0 :         AVCRawBinWriteDouble(psFile, psTxt->dHeight);
    1122               0 :         AVCRawBinWriteDouble(psFile, psTxt->dV2);
    1123               0 :         AVCRawBinWriteDouble(psFile, psTxt->dV3);
    1124                 :     }
    1125                 : 
    1126               0 :     if (nStrLen > 0)
    1127               0 :         AVCRawBinWritePaddedString(psFile, nStrLen, psTxt->pszText);
    1128                 : 
    1129               0 :     if (nPrecision == AVC_SINGLE_PREC)
    1130                 :     {
    1131               0 :         for(i=0; i<numVertices; i++)
    1132                 :         {
    1133               0 :             AVCRawBinWriteFloat(psFile, (float)psTxt->pasVertices[i].x);
    1134               0 :             AVCRawBinWriteFloat(psFile, (float)psTxt->pasVertices[i].y);
    1135                 :         }
    1136                 :     }
    1137                 :     else
    1138                 :     {
    1139               0 :         for(i=0; i<numVertices; i++)
    1140                 :         {
    1141               0 :             AVCRawBinWriteDouble(psFile, psTxt->pasVertices[i].x);
    1142               0 :             AVCRawBinWriteDouble(psFile, psTxt->pasVertices[i].y);
    1143                 :         }
    1144                 :     }
    1145                 : 
    1146               0 :     AVCRawBinWriteZeros(psFile, 8);
    1147                 : 
    1148                 :     /*-----------------------------------------------------------------
    1149                 :      * Write index entry (cnx.adf)
    1150                 :      *----------------------------------------------------------------*/
    1151               0 :     if (psIndexFile)
    1152                 :     {
    1153               0 :         _AVCBinWriteIndexEntry(psIndexFile, nCurPos, nRecSize);
    1154                 :     }
    1155                 : 
    1156               0 :     if (CPLGetLastErrorNo() != 0)
    1157               0 :         return -1;
    1158                 : 
    1159               0 :     return 0;
    1160                 : }
    1161                 : 
    1162                 : /**********************************************************************
    1163                 :  *                          _AVCBinWritePCCoverageTxt()
    1164                 :  *
    1165                 :  * (This function is for internal library use... external calls should
    1166                 :  * go to AVCBinWriteTxt() instead)
    1167                 :  *
    1168                 :  * Write a TXT (Annotation) structure to a AVCCoverPC file.
    1169                 :  *
    1170                 :  * The contents of the psTxt structure is assumed to be valid... this
    1171                 :  * function performs no validation on the consistency of what it is 
    1172                 :  * given as input.
    1173                 :  *
    1174                 :  * This function assumes that PC Coverages are always single precision.
    1175                 :  *
    1176                 :  * Returns 0 on success or -1 on error.
    1177                 :  **********************************************************************/
    1178               0 : int _AVCBinWritePCCoverageTxt(AVCRawBinFile *psFile, AVCTxt *psTxt, 
    1179                 :                               int nPrecision, AVCRawBinFile *psIndexFile)
    1180                 : {
    1181                 :     int i, nRecSize, nCurPos, nStrLen, numVertices;
    1182                 : 
    1183               0 :     CPLAssert(nPrecision == AVC_SINGLE_PREC);
    1184                 : 
    1185               0 :     nCurPos = psFile->nCurPos/2;  /* Value in 2 byte words */
    1186                 : 
    1187               0 :     AVCRawBinWriteInt32(psFile, psTxt->nTxtId);
    1188               0 :     if (CPLGetLastErrorNo() != 0)
    1189               0 :         return -1;
    1190                 : 
    1191                 :     /*-----------------------------------------------------------------
    1192                 :      * Record size is expressed in 2 byte words, and does not count the
    1193                 :      * first 8 bytes of the TXT entry.
    1194                 :      *----------------------------------------------------------------*/
    1195                 :     /* String uses a multiple of 4 bytes of storage,
    1196                 :      * And if text is already a multiple of 4 bytes then we include 4 extra 
    1197                 :      * spaces anyways (was probably a bug in the software!).
    1198                 :      */
    1199               0 :     if (psTxt->pszText)
    1200               0 :         nStrLen = ((strlen((char*)psTxt->pszText) + 4)/4)*4;
    1201                 :     else
    1202               0 :         nStrLen = 4;
    1203                 : 
    1204               0 :     nRecSize = (92 - 8 + nStrLen) / 2;
    1205                 : 
    1206               0 :     AVCRawBinWriteInt32(psFile, nRecSize);
    1207               0 :     AVCRawBinWriteInt32(psFile, psTxt->nLevel );
    1208                 : 
    1209                 :     /*-----------------------------------------------------------------
    1210                 :      * Number of vertices to write:
    1211                 :      * Note that because of the way V7 binary TXT files work, the rest of the
    1212                 :      * lib expects to receive duplicate coords for the first vertex, so
    1213                 :      * we will also receive an additional vertex for that but we won't write
    1214                 :      * it.  We also ignore the arrow vertices if there is any.
    1215                 :      *----------------------------------------------------------------*/
    1216               0 :     numVertices = ABS(psTxt->numVerticesLine) -1;
    1217               0 :     numVertices = MIN(4, numVertices);  /* Maximum of 4 points */
    1218                 : 
    1219               0 :     AVCRawBinWriteInt32(psFile, numVertices );
    1220                 : 
    1221               0 :     for(i=0; i<numVertices; i++)
    1222                 :     {
    1223               0 :         AVCRawBinWriteFloat(psFile, (float)psTxt->pasVertices[i+1].x);
    1224               0 :         AVCRawBinWriteFloat(psFile, (float)psTxt->pasVertices[i+1].y);
    1225                 :     }
    1226                 : 
    1227               0 :     AVCRawBinWriteZeros(psFile, (4-numVertices)*4*2 + 28);
    1228                 : 
    1229               0 :     AVCRawBinWriteFloat(psFile, (float)psTxt->dHeight);
    1230               0 :     AVCRawBinWriteFloat(psFile, psTxt->f_1e2 );
    1231               0 :     AVCRawBinWriteInt32(psFile, psTxt->nSymbol );
    1232               0 :     AVCRawBinWriteInt32(psFile, psTxt->numChars );
    1233                 : 
    1234               0 :     if (nStrLen > 0)
    1235               0 :         AVCRawBinWritePaddedString(psFile, nStrLen, psTxt->pszText);
    1236                 : 
    1237                 :     /*-----------------------------------------------------------------
    1238                 :      * Write index entry (cnx.adf)
    1239                 :      *----------------------------------------------------------------*/
    1240               0 :     if (psIndexFile)
    1241                 :     {
    1242               0 :         _AVCBinWriteIndexEntry(psIndexFile, nCurPos, nRecSize);
    1243                 :     }
    1244                 : 
    1245               0 :     if (CPLGetLastErrorNo() != 0)
    1246               0 :         return -1;
    1247                 : 
    1248               0 :     return 0;
    1249                 : }
    1250                 : 
    1251                 : 
    1252                 : /**********************************************************************
    1253                 :  *                          AVCBinWriteTxt()
    1254                 :  *
    1255                 :  * Write a TXT/TX6/TX7 (Annotation) structure to the file.
    1256                 :  *
    1257                 :  * The contents of the psTxt structure is assumed to be valid... this
    1258                 :  * function performs no validation on the consistency of what it is 
    1259                 :  * given as input.
    1260                 :  *
    1261                 :  * Returns 0 on success or -1 on error.
    1262                 :  *
    1263                 :  * If a problem happens, then CPLError() will be called by the lower-level
    1264                 :  * functions and CPLGetLastErrorNo() can be used to find out what happened.
    1265                 :  **********************************************************************/
    1266               0 : int AVCBinWriteTxt(AVCBinFile *psFile, AVCTxt *psTxt)
    1267                 : {
    1268               0 :     if (psFile->eFileType != AVCFileTXT && psFile->eFileType != AVCFileTX6)
    1269               0 :         return -1;
    1270                 : 
    1271                 :     /* AVCCoverPC and AVCCoverWeird have a different TXT format than AVCCoverV7
    1272                 :      */
    1273               0 :     if (psFile->eCoverType == AVCCoverPC || 
    1274               0 :         psFile->eCoverType == AVCCoverWeird)
    1275                 :     {
    1276               0 :         return _AVCBinWritePCCoverageTxt(psFile->psRawBinFile, psTxt,
    1277                 :                                          psFile->nPrecision, 
    1278                 :                                          psFile->psIndexFile);
    1279                 :     }
    1280                 :     else
    1281                 :     {
    1282               0 :         return _AVCBinWriteTxt(psFile->psRawBinFile, psTxt,
    1283                 :                                psFile->nPrecision, psFile->psIndexFile);
    1284                 :     }
    1285                 : }
    1286                 : 
    1287                 : /*=====================================================================
    1288                 :  *                              RXP
    1289                 :  *====================================================================*/
    1290                 : 
    1291                 : /**********************************************************************
    1292                 :  *                          _AVCBinWriteRxp()
    1293                 :  *
    1294                 :  * (This function is for internal library use... external calls should
    1295                 :  * go to AVCBinWriteRxp() instead)
    1296                 :  *
    1297                 :  * Write a RXP (Region something...) structure to the file.
    1298                 :  *
    1299                 :  * The contents of the psRxp structure is assumed to be valid... this
    1300                 :  * function performs no validation on the consistency of what it is 
    1301                 :  * given as input.
    1302                 :  *
    1303                 :  * Returns 0 on success or -1 on error.
    1304                 :  **********************************************************************/
    1305               0 : int _AVCBinWriteRxp(AVCRawBinFile *psFile, AVCRxp *psRxp, 
    1306                 :                     int nPrecision)
    1307                 : {
    1308                 : 
    1309               0 :     AVCRawBinWriteInt32(psFile, psRxp->n1);
    1310               0 :     if (CPLGetLastErrorNo() != 0)
    1311               0 :         return -1;
    1312                 : 
    1313               0 :     AVCRawBinWriteInt32(psFile, psRxp->n2);
    1314                 : 
    1315               0 :     if (CPLGetLastErrorNo() != 0)
    1316               0 :         return -1;
    1317                 : 
    1318               0 :     return 0;
    1319                 : }
    1320                 : 
    1321                 : /**********************************************************************
    1322                 :  *                          AVCBinWriteRxp()
    1323                 :  *
    1324                 :  * Write a  RXP (Region something...) structure to the file.
    1325                 :  *
    1326                 :  * The contents of the psRxp structure is assumed to be valid... this
    1327                 :  * function performs no validation on the consistency of what it is 
    1328                 :  * given as input.
    1329                 :  *
    1330                 :  * Returns 0 on success or -1 on error.
    1331                 :  *
    1332                 :  * If a problem happens, then CPLError() will be called by the lower-level
    1333                 :  * functions and CPLGetLastErrorNo() can be used to find out what happened.
    1334                 :  **********************************************************************/
    1335               0 : int AVCBinWriteRxp(AVCBinFile *psFile, AVCRxp *psRxp)
    1336                 : {
    1337               0 :     if (psFile->eFileType != AVCFileRXP)
    1338               0 :         return -1;
    1339                 : 
    1340               0 :     return _AVCBinWriteRxp(psFile->psRawBinFile, psRxp,
    1341                 :                            psFile->nPrecision);
    1342                 : }
    1343                 : 
    1344                 : 
    1345                 : /*=====================================================================
    1346                 :  *                              TABLES
    1347                 :  *====================================================================*/
    1348                 : 
    1349                 : /**********************************************************************
    1350                 :  *                          _AVCBinWriteArcDir()
    1351                 :  *
    1352                 :  * (This function is for internal library use... external calls should
    1353                 :  * go to AVCBinWriteCreateTable() instead)
    1354                 :  *
    1355                 :  * Write an ARC.DIR entry at the current position in file.
    1356                 :  *
    1357                 :  * The contents of the psTableDef structure is assumed to be valid... this
    1358                 :  * function performs no validation on the consistency of what it is 
    1359                 :  * given as input.
    1360                 :  *
    1361                 :  * Returns 0 on success or -1 on error.
    1362                 :  **********************************************************************/
    1363               0 : int _AVCBinWriteArcDir(AVCRawBinFile *psFile, AVCTableDef *psTableDef)
    1364                 : {
    1365                 :     /* STRING values MUST be padded with spaces.
    1366                 :      */
    1367               0 :     AVCRawBinWritePaddedString(psFile, 32, (GByte*)psTableDef->szTableName);
    1368               0 :     if (CPLGetLastErrorNo() != 0)
    1369               0 :         return -1;
    1370                 : 
    1371               0 :     AVCRawBinWritePaddedString(psFile, 8, (GByte*)psTableDef->szInfoFile);
    1372                 : 
    1373               0 :     AVCRawBinWriteInt16(psFile, psTableDef->numFields);
    1374                 : 
    1375                 :     /* Record size must be a multiple of 2 bytes */
    1376               0 :     AVCRawBinWriteInt16(psFile, (GInt16)(((psTableDef->nRecSize+1)/2)*2));
    1377                 : 
    1378                 :     /* ??? Unknown values ??? */
    1379               0 :     AVCRawBinWritePaddedString(psFile, 16, (GByte*)"                    ");
    1380               0 :     AVCRawBinWriteInt16(psFile, 132);
    1381               0 :     AVCRawBinWriteInt16(psFile, 0);
    1382                 : 
    1383               0 :     AVCRawBinWriteInt32(psFile, psTableDef->numRecords);
    1384                 : 
    1385               0 :     AVCRawBinWriteZeros(psFile, 10);
    1386                 : 
    1387               0 :     AVCRawBinWritePaddedString(psFile, 2, (GByte*)psTableDef->szExternal);
    1388                 : 
    1389               0 :     AVCRawBinWriteZeros(psFile, 238);
    1390               0 :     AVCRawBinWritePaddedString(psFile, 8, (GByte*)"                    ");
    1391               0 :     AVCRawBinWriteZeros(psFile, 54);
    1392                 : 
    1393               0 :     if (CPLGetLastErrorNo() != 0)
    1394               0 :         return -1;
    1395                 : 
    1396               0 :     return 0;
    1397                 : }
    1398                 : 
    1399                 : 
    1400                 : /**********************************************************************
    1401                 :  *                          _AVCBinWriteArcNit()
    1402                 :  *
    1403                 :  * (This function is for internal library use... external calls should
    1404                 :  * go to AVCBinWriteCreateTable() instead)
    1405                 :  *
    1406                 :  * Write an ARC####.NIT entry at the current position in file.
    1407                 :  *
    1408                 :  * The contents of the psTableDef structure is assumed to be valid... this
    1409                 :  * function performs no validation on the consistency of what it is 
    1410                 :  * given as input.
    1411                 :  *
    1412                 :  * Returns 0 on success or -1 on error.
    1413                 :  **********************************************************************/
    1414               0 : int _AVCBinWriteArcNit(AVCRawBinFile *psFile, AVCFieldInfo *psField)
    1415                 : {
    1416                 :     /* STRING values MUST be padded with spaces.
    1417                 :      */
    1418               0 :     AVCRawBinWritePaddedString(psFile, 16, (GByte*)psField->szName);
    1419               0 :     if (CPLGetLastErrorNo() != 0)
    1420               0 :         return -1;
    1421                 : 
    1422               0 :     AVCRawBinWriteInt16(psFile, psField->nSize);
    1423               0 :     AVCRawBinWriteInt16(psFile, psField->v2);
    1424               0 :     AVCRawBinWriteInt16(psFile, psField->nOffset);
    1425               0 :     AVCRawBinWriteInt16(psFile, psField->v4);
    1426               0 :     AVCRawBinWriteInt16(psFile, psField->v5);
    1427               0 :     AVCRawBinWriteInt16(psFile, psField->nFmtWidth);
    1428               0 :     AVCRawBinWriteInt16(psFile, psField->nFmtPrec);
    1429               0 :     AVCRawBinWriteInt16(psFile, psField->nType1);
    1430               0 :     AVCRawBinWriteInt16(psFile, psField->nType2);
    1431               0 :     AVCRawBinWriteInt16(psFile, psField->v10);
    1432               0 :     AVCRawBinWriteInt16(psFile, psField->v11);
    1433               0 :     AVCRawBinWriteInt16(psFile, psField->v12);
    1434               0 :     AVCRawBinWriteInt16(psFile, psField->v13);
    1435                 : 
    1436               0 :     AVCRawBinWritePaddedString(psFile, 16, (GByte*)psField->szAltName);
    1437                 : 
    1438               0 :     AVCRawBinWriteZeros(psFile, 56);
    1439                 : 
    1440               0 :     AVCRawBinWriteInt16(psFile, psField->nIndex);
    1441                 : 
    1442               0 :     AVCRawBinWriteZeros(psFile, 28);
    1443                 : 
    1444               0 :     if (CPLGetLastErrorNo() != 0)
    1445               0 :         return -1;
    1446                 : 
    1447               0 :     return 0;
    1448                 : }
    1449                 : 
    1450                 : 
    1451                 : /**********************************************************************
    1452                 :  *                     _AVCBinWriteCreateArcDirEntry()
    1453                 :  *
    1454                 :  * Add an entry in the ARC.DIR for the table defined in psSrcTableDef.
    1455                 :  *
    1456                 :  * If an entry with the same table name already exists then this entry
    1457                 :  * will be reused and overwritten.
    1458                 :  *
    1459                 :  * Note: there could be a problem if 2 processes try to add an entry
    1460                 :  * at the exact same time... does Arc/Info do any locking on that file???
    1461                 :  * 
    1462                 :  * Returns an integer value corresponding to the new table index (ARC####)
    1463                 :  * or -1 if something failed.
    1464                 :  **********************************************************************/
    1465                 : 
    1466                 : /* Prototype for _AVCBinReadNextArcDir() from avc_bin.c
    1467                 :  */
    1468                 : int _AVCBinReadNextArcDir(AVCRawBinFile *psFile, AVCTableDef *psArcDir);
    1469                 : 
    1470               0 : int _AVCBinWriteCreateArcDirEntry(const char *pszArcDirFile,
    1471                 :                                   AVCTableDef *psTableDef, 
    1472                 :                                   AVCDBCSInfo *psDBCSInfo)
    1473                 : {
    1474               0 :     int          iEntry, numDirEntries=0, nTableIndex = 0;
    1475                 :     VSIStatBuf   sStatBuf;
    1476                 :     AVCRawBinFile *hRawBinFile;
    1477                 :     GBool        bFound;
    1478                 :     AVCTableDef  sEntry;
    1479                 : 
    1480                 :     /*-----------------------------------------------------------------
    1481                 :      * Open and Scan the ARC.DIR to establish the table index (ARC####)
    1482                 :      *----------------------------------------------------------------*/
    1483                 : #ifdef _WIN32
    1484                 :     /*-----------------------------------------------------------------
    1485                 :      * Note, DM, 20010507 - We used to use VSIFStat() to establish the
    1486                 :      * size of arc.dir, but when working on a WinNT4 networked drive, the
    1487                 :      * stat() information was not always right, and we sometimes ended 
    1488                 :      * up overwriting arc.dir entries.  The solution: open and scan arc.dir
    1489                 :      * until EOF to establish its size.  
    1490                 :      * That trick also seems to fix another network buffer problem: when 
    1491                 :      * writing a coverage in a new empty dir (with no info dir yet), we
    1492                 :      * would get an error in fwrite() while writing the 3rd arc.dir 
    1493                 :      * entry of the coverage.  That second problem could also have been 
    1494                 :      * fixed by forcing a VSIFSeek() before the first fwrite()... we've 
    1495                 :      * added it below.
    1496                 :      *----------------------------------------------------------------*/
    1497                 :     FILE *fp;
    1498                 :     if ((fp = VSIFOpen(pszArcDirFile, "r")) != NULL)
    1499                 :     {
    1500                 :         char buf[380];
    1501                 :         while (!VSIFEof(fp))
    1502                 :         {
    1503                 :             if (VSIFRead(buf, 380, 1, fp) == 1)
    1504                 :                 numDirEntries++;
    1505                 :         }
    1506                 :         VSIFClose(fp);
    1507                 :         hRawBinFile = AVCRawBinOpen(pszArcDirFile, "r+",
    1508                 :                                     AVC_COVER_BYTE_ORDER(AVCCoverV7),
    1509                 :                                     psDBCSInfo);
    1510                 :     }
    1511                 :     else 
    1512                 : #endif
    1513                 :     /* On Unix we can still use fstat() */
    1514               0 :     if ( VSIStat(pszArcDirFile, &sStatBuf) != -1 )
    1515                 :     {
    1516               0 :         numDirEntries = sStatBuf.st_size/380;
    1517               0 :         hRawBinFile = AVCRawBinOpen(pszArcDirFile, "r+",
    1518                 :                                     AVC_COVER_BYTE_ORDER(AVCCoverV7),
    1519                 :                                     psDBCSInfo);
    1520                 :     }
    1521                 :     else
    1522                 :     {
    1523               0 :         numDirEntries = 0;
    1524               0 :         hRawBinFile = AVCRawBinOpen(pszArcDirFile, "w", 
    1525                 :                                     AVC_COVER_BYTE_ORDER(AVCCoverV7), 
    1526                 :                                     psDBCSInfo);
    1527                 :     }
    1528                 : 
    1529               0 :     if (hRawBinFile == NULL)
    1530                 :     {
    1531                 :         /* Failed to open file... just return -1 since an error message
    1532                 :          * has already been issued by AVCRawBinOpen()
    1533                 :          */
    1534               0 :         return -1;
    1535                 :     }
    1536                 : 
    1537                 :     /* Init nTableIndex at -1 so that first table created should have 
    1538                 :      * index 0 
    1539                 :      */
    1540               0 :     nTableIndex = -1;
    1541               0 :     iEntry = 0;
    1542               0 :     bFound = FALSE;
    1543               0 :     while(!bFound && iEntry<numDirEntries &&
    1544               0 :           _AVCBinReadNextArcDir(hRawBinFile, &sEntry) == 0)
    1545                 :     {
    1546               0 :         nTableIndex = atoi(sEntry.szInfoFile+3);
    1547               0 :         if (EQUALN(psTableDef->szTableName, sEntry.szTableName, 
    1548                 :                    strlen(psTableDef->szTableName)))
    1549                 :         {   
    1550               0 :             bFound = TRUE;
    1551               0 :             break;
    1552                 :         }
    1553               0 :         iEntry++;
    1554                 :     }
    1555                 : 
    1556                 :     /*-----------------------------------------------------------------
    1557                 :      * Reposition the file pointer and write the entry.
    1558                 :      *
    1559                 :      * We use VSIFSeek() directly since the AVCRawBin*() functions do
    1560                 :      * not support random access yet... it is OK to do so here since the
    1561                 :      * ARC.DIR does not have a header and we will close it right away.
    1562                 :      *----------------------------------------------------------------*/
    1563               0 :     if (bFound)
    1564               0 :         VSIFSeek(hRawBinFile->fp, iEntry*380, SEEK_SET);
    1565                 :     else
    1566                 :     {
    1567                 :         /* Not found... Use the next logical table index */
    1568               0 :         nTableIndex++;
    1569                 : 
    1570                 :         /* We're already at EOF so we shouldn't need to fseek here, but
    1571                 :          * ANSI-C requires that a file positioning function be called 
    1572                 :          * between read and writes... this had never been a problem before
    1573                 :          * on any system except with NT4 network drives.
    1574                 :          */
    1575               0 :         VSIFSeek(hRawBinFile->fp, numDirEntries*380, SEEK_SET);
    1576                 :     }
    1577                 : 
    1578               0 :     sprintf(psTableDef->szInfoFile, "ARC%4.4d", nTableIndex);
    1579               0 :     _AVCBinWriteArcDir(hRawBinFile, psTableDef);
    1580                 : 
    1581               0 :     AVCRawBinClose(hRawBinFile);
    1582                 : 
    1583               0 :     return nTableIndex;
    1584                 : }
    1585                 : 
    1586                 : 
    1587                 : /**********************************************************************
    1588                 :  *                          AVCBinWriteCreateTable()
    1589                 :  *
    1590                 :  * Open an INFO table for writing:
    1591                 :  *
    1592                 :  *  - Add an entry for the new table in the info/arc.dir
    1593                 :  *  - Write the attributes definitions to the info/arc####.nit
    1594                 :  *  - Create the data file, ready to write data records to it
    1595                 :  *  - If necessary, set the arc####.dat to point to the location of
    1596                 :  *    the data file.
    1597                 :  *
    1598                 :  * pszInfoPath is the info directory path, terminated by a '/' or a '\\'
    1599                 :  * It is assumed that this 'info' directory already exists and is writable.
    1600                 :  *
    1601                 :  * psTableDef should contain a valid table definition for this coverage.
    1602                 :  * This function will create and maintain its own copy of the structure.
    1603                 :  *
    1604                 :  * The name of the file to create and its location will be based on the 
    1605                 :  * table name and the external ("XX") flag values in the psTableDef 
    1606                 :  * structure, so you have to make sure that these values are valid.
    1607                 :  *
    1608                 :  * If a table with the same name is already present in the arc.dir, then 
    1609                 :  * the same arc.dir entry will be used and overwritten.  This happens
    1610                 :  * when a coverage directory is deleted by hand.  The behavior implemented
    1611                 :  * here correspond to Arc/Info's behavior.
    1612                 :  *
    1613                 :  * For internal tables, the data file goes directly in the info directory, so
    1614                 :  * there is not much to worry about.
    1615                 :  *
    1616                 :  * For external tables, the table name is composed of 3 parts:
    1617                 :  *
    1618                 :  *         <COVERNAME>.<EXT><SUBCLASSNAME>
    1619                 :  *
    1620                 :  *  - <COVERNAME>:
    1621                 :  *    The first part of the table name (before the '.') is the
    1622                 :  *    name of the coverage to which the table belongs, and the data file
    1623                 :  *    will be created in this coverage's directory... so it is assumed that
    1624                 :  *    the directory "../<covername>" already exists and is writable.
    1625                 :  *  - <EXT>:
    1626                 :  *    The coverage name is followed by a 3 chars extension that will be 
    1627                 :  *    used to build the name of the external table to create.
    1628                 :  *  - <SUBCLASSNAME>:
    1629                 :  *    For some table types, the extension is followed by a subclass name.
    1630                 :  *    
    1631                 :  *  When <SUBCLASSNAME> is present, then the data file name will be:
    1632                 :  *            "../<covername>/<subclassname>.<ext>"
    1633                 :  *
    1634                 :  *    e.g. The table named "TEST.PATCOUNTY" would be stored in the file
    1635                 :  *         "../test/county.pat" (this path is realtive to the info directory)
    1636                 :  *
    1637                 :  *  When the <SUBCLASSNAME> is not present, then the name of the data file
    1638                 :  *  will be the "../<covername>/<ext>.adf"
    1639                 :  *
    1640                 :  *    e.g. The table named "TEST.PAT" would be stored in the file 
    1641                 :  *         "../test/pat.adf"
    1642                 :  *
    1643                 :  * Of course, it would be too easy if there were no exceptions to these
    1644                 :  * rules!  Single precision ".TIC" and ".BND" follow the above rules and
    1645                 :  * will be named "tic.adf" and "bnd.adf" but in double precision coverages,
    1646                 :  * they will be named "dbltic.adf" and "dblbnd.adf".
    1647                 :  *
    1648                 :  * Returns a valid AVCBinFile handle, or NULL if the table could
    1649                 :  * not be created.
    1650                 :  *
    1651                 :  * AVCBinClose() will eventually have to be called to release the 
    1652                 :  * resources used by the AVCBinFile structure.
    1653                 :  **********************************************************************/
    1654               0 : AVCBinFile *AVCBinWriteCreateTable(const char *pszInfoPath, 
    1655                 :                                    const char *pszCoverName,
    1656                 :                                    AVCTableDef *psSrcTableDef,
    1657                 :                                    AVCCoverType eCoverType,
    1658                 :                                    int nPrecision, AVCDBCSInfo *psDBCSInfo)
    1659                 : {
    1660                 :     AVCBinFile   *psFile;
    1661                 :     AVCRawBinFile *hRawBinFile;
    1662               0 :     AVCTableDef  *psTableDef = NULL;
    1663               0 :     char         *pszFname = NULL, szInfoFile[8]="";
    1664               0 :     int          i, nTableIndex = 0;
    1665                 : 
    1666               0 :     if (eCoverType == AVCCoverPC || eCoverType == AVCCoverPC2)
    1667               0 :         return _AVCBinWriteCreateDBFTable(pszInfoPath, pszCoverName,
    1668                 :                                           psSrcTableDef, eCoverType, 
    1669                 :                                           nPrecision, psDBCSInfo);
    1670                 : 
    1671                 :     /*-----------------------------------------------------------------
    1672                 :      * Make sure precision value is valid (AVC_DEFAULT_PREC is NOT valid)
    1673                 :      *----------------------------------------------------------------*/
    1674               0 :     if (nPrecision!=AVC_SINGLE_PREC && nPrecision!=AVC_DOUBLE_PREC)
    1675                 :     {
    1676               0 :         CPLError(CE_Failure, CPLE_IllegalArg,
    1677                 :                  "AVCBinWriteCreateTable(): Invalid precision parameter "
    1678                 :                  "(value must be AVC_SINGLE_PREC or AVC_DOUBLE_PREC)");
    1679               0 :         return NULL;
    1680                 :     }
    1681                 : 
    1682                 :     /* Alloc a buffer big enough for the longest possible filename...
    1683                 :      */
    1684               0 :     pszFname = (char*)CPLMalloc((strlen(pszInfoPath)+81)*sizeof(char));
    1685                 : 
    1686                 : 
    1687                 :     /*-----------------------------------------------------------------
    1688                 :      * Alloc and init the AVCBinFile struct.
    1689                 :      *----------------------------------------------------------------*/
    1690               0 :     psFile = (AVCBinFile*)CPLCalloc(1, sizeof(AVCBinFile));
    1691                 : 
    1692               0 :     psFile->eFileType = AVCFileTABLE;
    1693                 :     /* Precision is not important for tables */
    1694               0 :     psFile->nPrecision = nPrecision;
    1695               0 :     psFile->eCoverType = eCoverType;
    1696                 : 
    1697               0 :     psFile->hdr.psTableDef = psTableDef = _AVCDupTableDef(psSrcTableDef);
    1698                 : 
    1699                 :     /*-----------------------------------------------------------------
    1700                 :      * Add a record for this table in the "arc.dir"
    1701                 :      * Note: there could be a problem if 2 processes try to add an entry
    1702                 :      * at the exact same time... does Arc/Info do any locking on that file???
    1703                 :      *----------------------------------------------------------------*/
    1704               0 :     sprintf(pszFname, "%sarc.dir", pszInfoPath);
    1705                 : 
    1706               0 :     nTableIndex = _AVCBinWriteCreateArcDirEntry(pszFname, psTableDef, 
    1707                 :                                                 psDBCSInfo);
    1708                 : 
    1709               0 :     if (nTableIndex < 0)
    1710                 :     {
    1711                 :         /* Failed to add arc.dir entry... just return NULL since an error
    1712                 :          * message has already been issued by _AVCBinWriteCreateArcDirEntry()
    1713                 :          */
    1714               0 :         _AVCDestroyTableDef(psTableDef);
    1715               0 :         CPLFree(psFile);
    1716               0 :         CPLFree(pszFname);
    1717               0 :         return NULL;
    1718                 :     }
    1719                 : 
    1720               0 :     sprintf(szInfoFile, "arc%4.4d", nTableIndex);
    1721                 : 
    1722                 :     /*-----------------------------------------------------------------
    1723                 :      * Create the "arc####.nit" with the attribute definitions.
    1724                 :      *----------------------------------------------------------------*/
    1725               0 :     sprintf(pszFname, "%s%s.nit", pszInfoPath, szInfoFile);
    1726                 : 
    1727               0 :     hRawBinFile = AVCRawBinOpen(pszFname, "w",
    1728                 :                                 AVC_COVER_BYTE_ORDER(AVCCoverV7),
    1729                 :                                 psDBCSInfo);
    1730                 : 
    1731               0 :     if (hRawBinFile == NULL)
    1732                 :     {
    1733                 :         /* Failed to open file... just return NULL since an error message
    1734                 :          * has already been issued by AVCRawBinOpen()
    1735                 :          */
    1736               0 :         _AVCDestroyTableDef(psTableDef);
    1737               0 :         CPLFree(psFile);
    1738               0 :         CPLFree(pszFname);
    1739               0 :         return NULL;
    1740                 :     }
    1741                 : 
    1742               0 :     for(i=0; i<psTableDef->numFields; i++)
    1743                 :     {
    1744               0 :         _AVCBinWriteArcNit(hRawBinFile, &(psTableDef->pasFieldDef[i]));
    1745                 :     }
    1746                 : 
    1747               0 :     AVCRawBinClose(hRawBinFile);
    1748               0 :     hRawBinFile = NULL;
    1749                 : 
    1750                 :     /*-----------------------------------------------------------------
    1751                 :      * The location of the data file depends on the external flag.
    1752                 :      *----------------------------------------------------------------*/
    1753               0 :     if (EQUAL(psTableDef->szExternal, "  "))
    1754                 :     {
    1755                 :         /*-------------------------------------------------------------
    1756                 :          * Internal table: data goes directly in "arc####.dat"
    1757                 :          *------------------------------------------------------------*/
    1758               0 :         psTableDef->szDataFile[0] = '\0';
    1759               0 :         sprintf(pszFname, "%s%s.dat", pszInfoPath, szInfoFile);
    1760               0 :         psFile->pszFilename = CPLStrdup(pszFname);
    1761                 :     }
    1762                 :     else
    1763                 :     {
    1764                 :         /*-------------------------------------------------------------
    1765                 :          * External table: data stored in the coverage directory, and
    1766                 :          * the path to the data file is written to "arc####.dat"
    1767                 :          *... start by extracting the info to build the data file name...
    1768                 :          *------------------------------------------------------------*/
    1769               0 :         char szCoverName[40]="", szExt[4]="", szSubclass[40]="", *pszPtr;
    1770                 :         int nLen;
    1771                 :         FILE *fpOut;
    1772                 : 
    1773               0 :         nLen = strlen(psTableDef->szTableName);
    1774               0 :         CPLAssert(nLen <= 32);
    1775               0 :         if (nLen > 32) return NULL;
    1776               0 :         pszPtr = psTableDef->szTableName;
    1777                 : 
    1778               0 :         for(i=0; *pszPtr!='\0' && *pszPtr!='.' && *pszPtr!=' ';  i++, pszPtr++)
    1779                 :         {
    1780               0 :             szCoverName[i] = tolower(*pszPtr);
    1781                 :         }
    1782               0 :         szCoverName[i] = '\0';
    1783                 : 
    1784               0 :         if (*pszPtr == '.')
    1785               0 :             pszPtr++;
    1786                 : 
    1787               0 :         for(i=0; i<3 && *pszPtr!='\0' && *pszPtr!=' ';  i++, pszPtr++)
    1788                 :         {
    1789               0 :             szExt[i] = tolower(*pszPtr);
    1790                 :         }
    1791               0 :         szExt[i] = '\0';
    1792                 : 
    1793               0 :         for(i=0; *pszPtr!='\0' && *pszPtr!=' ';  i++, pszPtr++)
    1794                 :         {
    1795               0 :             szSubclass[i] = tolower(*pszPtr);
    1796                 :         }
    1797               0 :         szSubclass[i] = '\0';
    1798                 : 
    1799                 :         /*-------------------------------------------------------------
    1800                 :          * ... and build the data file name based on what we extracted
    1801                 :          *------------------------------------------------------------*/
    1802               0 :         if (strlen(szSubclass) == 0)
    1803                 :         {
    1804               0 :             if (nPrecision == AVC_DOUBLE_PREC &&
    1805               0 :                 (EQUAL(szExt, "TIC") || EQUAL(szExt, "BND")) )
    1806                 :             {
    1807                 :                 /* "../<covername>/dbl<ext>.adf" */
    1808               0 :                 sprintf(psTableDef->szDataFile, 
    1809                 :                         "../%s/dbl%s.adf", szCoverName, szExt);
    1810                 :             }
    1811                 :             else
    1812                 :             {
    1813                 :                 /* "../<covername>/<ext>.adf" */
    1814               0 :                 sprintf(psTableDef->szDataFile, 
    1815                 :                         "../%s/%s.adf", szCoverName, szExt);
    1816                 :             }
    1817                 :         }
    1818                 :         else
    1819                 :         {
    1820                 :             /* "../<covername>/<subclass>.<ext>" */
    1821               0 :             sprintf(psTableDef->szDataFile, 
    1822                 :                     "../%s/%s.%s", szCoverName, szSubclass, szExt);
    1823                 :         }
    1824                 : 
    1825                 :         /*-------------------------------------------------------------
    1826                 :          * Write it to the arc####.dat
    1827                 :          * Note that the path that is written in the arc####.dat contains
    1828                 :          * '/' as a directory delimiter, even on Windows systems.
    1829                 :          *------------------------------------------------------------*/
    1830               0 :         sprintf(pszFname, "%s%s.dat", pszInfoPath, szInfoFile);
    1831               0 :         fpOut = VSIFOpen(pszFname, "wt");
    1832               0 :         if (fpOut)
    1833                 :         {
    1834               0 :             VSIFPrintf(fpOut, "%-80.80s", psTableDef->szDataFile);
    1835               0 :             VSIFClose(fpOut);
    1836                 :         }
    1837                 :         else
    1838                 :         {
    1839               0 :             CPLError(CE_Failure, CPLE_OpenFailed,
    1840                 :                      "Failed creating file %s.", pszFname);
    1841               0 :             CPLFree(pszFname);
    1842               0 :             _AVCDestroyTableDef(psTableDef);
    1843               0 :             CPLFree(psFile);
    1844               0 :             return NULL;
    1845                 :         }
    1846                 : 
    1847               0 :         sprintf(pszFname, "%s%s", 
    1848                 :                 pszInfoPath, psTableDef->szDataFile);
    1849               0 :         psFile->pszFilename = CPLStrdup(pszFname);
    1850                 : 
    1851                 : #ifdef WIN32
    1852                 :         /*-------------------------------------------------------------
    1853                 :          * On a Windows system, we have to change the '/' to '\\' in the
    1854                 :          * data file path.
    1855                 :          *------------------------------------------------------------*/
    1856                 :         for(i=0; psFile->pszFilename[i] != '\0'; i++)
    1857                 :             if (psFile->pszFilename[i] == '/')
    1858                 :                 psFile->pszFilename[i] = '\\';
    1859                 : #endif /* WIN32 */
    1860                 : 
    1861                 :     }/* if "XX" */
    1862                 : 
    1863                 :     /*-----------------------------------------------------------------
    1864                 :      * OK, now we're ready to create the actual data file.
    1865                 :      *----------------------------------------------------------------*/
    1866               0 :     AVCAdjustCaseSensitiveFilename(psFile->pszFilename);
    1867               0 :     psFile->psRawBinFile = AVCRawBinOpen(psFile->pszFilename, "w",
    1868                 :                                          AVC_COVER_BYTE_ORDER(AVCCoverV7),
    1869                 :                                          psDBCSInfo);
    1870                 : 
    1871               0 :     if (psFile->psRawBinFile == NULL)
    1872                 :     {
    1873                 :         /* Failed to open file... just return NULL since an error message
    1874                 :          * has already been issued by AVCRawBinOpen()
    1875                 :          */
    1876               0 :         CPLFree(pszFname);
    1877               0 :         CPLFree(psFile->pszFilename);
    1878               0 :         _AVCDestroyTableDef(psTableDef);
    1879               0 :         CPLFree(psFile);
    1880               0 :         return NULL;
    1881                 :     }
    1882                 : 
    1883               0 :     CPLFree(pszFname);
    1884                 : 
    1885               0 :     return psFile;
    1886                 : }
    1887                 : 
    1888                 : 
    1889                 : /**********************************************************************
    1890                 :  *                          _AVCBinWriteCreateDBFTable()
    1891                 :  *
    1892                 :  * Create a table (DBF file) in a PC Coverage and write the attribute defns to
    1893                 :  * the file.  The file will then be ready to write records to.
    1894                 :  *
    1895                 :  * In PC Coverages, only the following tables appear to be supported:
    1896                 :  *    - TEST.AAT -> AAT.DBF
    1897                 :  *    - TEST.PAT -> PAT.DBF
    1898                 :  *    - TEST.BND -> BND.DBF
    1899                 :  *    - TEST.TIC -> TIC.DBF
    1900                 :  *
    1901                 :  * However, this function will not fail if it is passed a table name not 
    1902                 :  * supported by PC Arc/Info. 
    1903                 :  * e.g. TEST.PATCOUNTY would be written as PATCOUNTY.DBF even if PC Arc/Info
    1904                 :  * would probably not recognize that name.
    1905                 :  *
    1906                 :  * Returns a valid AVCBinFile handle, or NULL if the table could
    1907                 :  * not be created.
    1908                 :  *
    1909                 :  * AVCBinClose() will eventually have to be called to release the 
    1910                 :  * resources used by the AVCBinFile structure.
    1911                 :  **********************************************************************/
    1912               0 : AVCBinFile *_AVCBinWriteCreateDBFTable(const char *pszPath, 
    1913                 :                                        const char *pszCoverName,
    1914                 :                                        AVCTableDef *psSrcTableDef,
    1915                 :                                        AVCCoverType eCoverType,
    1916                 :                                        int nPrecision, AVCDBCSInfo *psDBCSInfo)
    1917                 : {
    1918                 :     AVCBinFile    *psFile;
    1919               0 :     AVCTableDef   *psTableDef = NULL;
    1920                 :     AVCFieldInfo  *pasDef;
    1921                 :     char          *pszDBFBasename, szFieldName[12];
    1922                 :     int           i, j, nType;
    1923                 : 
    1924                 :     /*-----------------------------------------------------------------
    1925                 :      * Alloc and init the AVCBinFile struct.
    1926                 :      *----------------------------------------------------------------*/
    1927               0 :     psFile = (AVCBinFile*)CPLCalloc(1, sizeof(AVCBinFile));
    1928                 : 
    1929               0 :     psFile->eFileType = AVCFileTABLE;
    1930                 :     /* Precision is not important for tables */
    1931               0 :     psFile->nPrecision = nPrecision;
    1932               0 :     psFile->eCoverType = eCoverType;
    1933                 : 
    1934               0 :     psFile->hdr.psTableDef = psTableDef = _AVCDupTableDef(psSrcTableDef);
    1935                 : 
    1936                 :     /* nCurDBFRecord is used to keep track of the 0-based index of the
    1937                 :      * last record we read from the DBF file... this is to emulate 
    1938                 :      * sequential access which is assumed by the rest of the lib.
    1939                 :      * Since the first record (record 0) has not been written yet, then
    1940                 :      * we init the index at -1.
    1941                 :      */
    1942               0 :     psFile->nCurDBFRecord = -1;
    1943                 : 
    1944                 :     /*-----------------------------------------------------------------
    1945                 :      * Establish name of file to create.
    1946                 :      *----------------------------------------------------------------*/
    1947               0 :     psFile->pszFilename = (char*)CPLCalloc(strlen(psSrcTableDef->szTableName)+
    1948               0 :                                            strlen(pszPath)+10, sizeof(char));
    1949                 : 
    1950               0 :     if (EQUALN(psSrcTableDef->szTableName, pszCoverName, strlen(pszCoverName))
    1951               0 :         && psSrcTableDef->szTableName[strlen(pszCoverName)] == '.')
    1952                 :     {
    1953               0 :         pszDBFBasename = psSrcTableDef->szTableName + strlen(pszCoverName)+1;
    1954                 :     }
    1955                 :     else
    1956                 :     {
    1957               0 :         pszDBFBasename = psSrcTableDef->szTableName;
    1958                 :     }
    1959                 : 
    1960               0 :     strcpy(psFile->pszFilename, pszPath);
    1961                 : 
    1962               0 :     for(i=strlen(psFile->pszFilename); *pszDBFBasename; i++, pszDBFBasename++)
    1963                 :     {
    1964               0 :         psFile->pszFilename[i] = tolower(*pszDBFBasename);
    1965                 :     }
    1966                 : 
    1967               0 :     strcat(psFile->pszFilename, ".dbf");
    1968                 : 
    1969                 :     /*-----------------------------------------------------------------
    1970                 :      * OK, let's try to create the DBF file.
    1971                 :      *----------------------------------------------------------------*/
    1972               0 :     AVCAdjustCaseSensitiveFilename(psFile->pszFilename);
    1973               0 :     psFile->hDBFFile = DBFCreate(psFile->pszFilename);
    1974                 : 
    1975               0 :     if (psFile->hDBFFile == NULL)
    1976                 :     {
    1977               0 :         CPLError(CE_Failure, CPLE_OpenFailed,
    1978                 :                  "Failed creating file %s.", psFile->pszFilename);
    1979               0 :         CPLFree(psFile->pszFilename);
    1980               0 :         _AVCDestroyTableDef(psTableDef);
    1981               0 :         CPLFree(psFile);
    1982               0 :         return NULL;
    1983                 :     }
    1984                 : 
    1985                 :     /*-----------------------------------------------------------------
    1986                 :      * Create fields.
    1987                 :      *----------------------------------------------------------------*/
    1988               0 :     pasDef = psTableDef->pasFieldDef;
    1989               0 :     for(i=0; i<psTableDef->numFields; i++)
    1990                 :     {
    1991               0 :         nType = pasDef[i].nType1*10;
    1992                 : 
    1993                 :         /*-------------------------------------------------------------
    1994                 :          * Special characters '#' and '-' in field names have to be replaced 
    1995                 :          * with '_'.  PC Field names are limited to 10 chars.
    1996                 :          *------------------------------------------------------------*/
    1997               0 :         strncpy(szFieldName, pasDef[i].szName, 10);
    1998               0 :         szFieldName[10] = '\0';
    1999               0 :         for(j=0; szFieldName[j]; j++)
    2000                 :         {
    2001               0 :             if (szFieldName[j] == '#' || szFieldName[j] == '-')
    2002               0 :                 szFieldName[j] = '_';
    2003                 :         }
    2004                 : 
    2005               0 :         if (nType ==  AVC_FT_DATE || nType == AVC_FT_CHAR)
    2006                 :         {
    2007                 :             /*---------------------------------------------------------
    2008                 :              * Values stored as strings
    2009                 :              *--------------------------------------------------------*/
    2010               0 :             DBFAddField(psFile->hDBFFile, szFieldName, FTString, 
    2011               0 :                         pasDef[i].nSize, 0);
    2012                 :         }
    2013               0 :         else if (nType == AVC_FT_FIXINT || nType == AVC_FT_FIXNUM)
    2014                 :         {
    2015                 :             /*---------------------------------------------------------
    2016                 :              * Numerics (internally stored as strings)
    2017                 :              *--------------------------------------------------------*/
    2018               0 :             DBFAddField(psFile->hDBFFile, szFieldName, FTDouble, 
    2019               0 :                         pasDef[i].nSize, pasDef[i].nFmtPrec);
    2020                 :         }
    2021               0 :         else if (nType == AVC_FT_BININT)
    2022                 :         {
    2023                 :             /*---------------------------------------------------------
    2024                 :              * Integers (16 and 32 bits)
    2025                 :              *--------------------------------------------------------*/
    2026               0 :             DBFAddField(psFile->hDBFFile, szFieldName, FTInteger, 11, 0);
    2027                 :         }
    2028               0 :         else if (nType == AVC_FT_BINFLOAT)
    2029                 :         {
    2030                 :             /*---------------------------------------------------------
    2031                 :              * Single + Double precision floats
    2032                 :              * Set them as width=13, prec=6 in the header like PC/Arc does
    2033                 :              *--------------------------------------------------------*/
    2034               0 :             DBFAddField(psFile->hDBFFile, szFieldName, FTDouble, 
    2035                 :                         13, 6);
    2036                 :         }
    2037                 :         else
    2038                 :         {
    2039                 :             /*---------------------------------------------------------
    2040                 :              * Hummm... unsupported field type...
    2041                 :              *--------------------------------------------------------*/
    2042               0 :             CPLError(CE_Failure, CPLE_NotSupported,
    2043                 :                      "Unsupported field type: (field=%s, type=%d, size=%d)",
    2044               0 :                      szFieldName, nType, pasDef[i].nSize);
    2045               0 :             _AVCBinWriteCloseTable(psFile);
    2046               0 :             return NULL;
    2047                 :         }
    2048                 :     }
    2049                 : 
    2050               0 :     return psFile;
    2051                 : }
    2052                 : 
    2053                 : 
    2054                 : /**********************************************************************
    2055                 :  *                          _AVCBinWriteCloseTable()
    2056                 :  *
    2057                 :  * (This function is for internal library use... external calls should
    2058                 :  * go to AVCBinWriteClose() instead)
    2059                 :  *
    2060                 :  * Close an info table opened for wirting, and release all memory 
    2061                 :  * (object struct., buffers, etc.) associated with this file.
    2062                 :  **********************************************************************/
    2063               0 : static void    _AVCBinWriteCloseTable(AVCBinFile *psFile)
    2064                 : {
    2065               0 :     if (psFile->eFileType != AVCFileTABLE)
    2066               0 :         return;
    2067                 : 
    2068                 :     /*-----------------------------------------------------------------
    2069                 :      * Close the data file
    2070                 :      *----------------------------------------------------------------*/
    2071               0 :     if (psFile->hDBFFile)
    2072                 :     {
    2073                 :         /*-------------------------------------------------------------
    2074                 :          * The case of DBF files is simple!
    2075                 :          *------------------------------------------------------------*/
    2076               0 :         DBFClose(psFile->hDBFFile);
    2077               0 :         psFile->hDBFFile = NULL;
    2078                 :     }
    2079               0 :     else if (psFile->psRawBinFile)
    2080                 :     {
    2081                 :         /*-------------------------------------------------------------
    2082                 :          * __TODO__ make sure ARC.DIR entry contains accurate info about the 
    2083                 :          * number of records written, etc.
    2084                 :          *------------------------------------------------------------*/
    2085               0 :         AVCRawBinClose(psFile->psRawBinFile);
    2086               0 :         psFile->psRawBinFile = NULL;
    2087                 :     }
    2088                 : 
    2089                 :     /*-----------------------------------------------------------------
    2090                 :      * Release other memory
    2091                 :      *----------------------------------------------------------------*/
    2092               0 :     _AVCDestroyTableDef(psFile->hdr.psTableDef);
    2093                 : 
    2094               0 :     CPLFree(psFile->pszFilename);
    2095                 : 
    2096               0 :     CPLFree(psFile);
    2097                 : }
    2098                 : 
    2099                 : 
    2100                 : /**********************************************************************
    2101                 :  *                          _AVCBinWriteTableRec()
    2102                 :  *
    2103                 :  * (This function is for internal library use... external calls should
    2104                 :  * go to AVCBinWriteTableRec() instead)
    2105                 :  *
    2106                 :  * Write a table data record at the current position in file.
    2107                 :  *
    2108                 :  * The contents of the pasDef and pasFields structures is assumed to 
    2109                 :  * be valid... this function performs no validation on the consistency 
    2110                 :  * of what it is given as input.
    2111                 :  *
    2112                 :  * Returns 0 on success or -1 on error.
    2113                 :  **********************************************************************/
    2114               0 : int _AVCBinWriteTableRec(AVCRawBinFile *psFile, int nFields,
    2115                 :                          AVCFieldInfo *pasDef, AVCField *pasFields,
    2116                 :                          int nRecordSize, const char *pszFname)
    2117                 : {
    2118               0 :     int i, nType, nBytesWritten=0;
    2119                 : 
    2120               0 :     if (psFile == NULL)
    2121               0 :         return -1;
    2122                 : 
    2123               0 :     for(i=0; i<nFields; i++)
    2124                 :     {
    2125               0 :         if (CPLGetLastErrorNo() != 0)
    2126               0 :             return -1;
    2127                 : 
    2128               0 :         nType = pasDef[i].nType1*10;
    2129                 : 
    2130               0 :         if (nType ==  AVC_FT_DATE || nType == AVC_FT_CHAR ||
    2131                 :             nType == AVC_FT_FIXINT || nType == AVC_FT_FIXNUM)
    2132                 :         {
    2133                 :             /*---------------------------------------------------------
    2134                 :              * Values stored as strings (MUST be padded with spaces)
    2135                 :              *--------------------------------------------------------*/
    2136               0 :             AVCRawBinWritePaddedString(psFile, pasDef[i].nSize,
    2137               0 :                                        pasFields[i].pszStr);
    2138                 :         }
    2139               0 :         else if (nType == AVC_FT_BININT && pasDef[i].nSize == 4)
    2140                 :         {
    2141                 :             /*---------------------------------------------------------
    2142                 :              * 32 bit binary integers
    2143                 :              *--------------------------------------------------------*/
    2144               0 :             AVCRawBinWriteInt32(psFile, pasFields[i].nInt32);
    2145                 :         }
    2146               0 :         else if (nType == AVC_FT_BININT && pasDef[i].nSize == 2)
    2147                 :         {
    2148                 :             /*---------------------------------------------------------
    2149                 :              * 16 bit binary integers
    2150                 :              *--------------------------------------------------------*/
    2151               0 :             AVCRawBinWriteInt16(psFile, pasFields[i].nInt16);
    2152                 :         }
    2153               0 :         else if (nType == AVC_FT_BINFLOAT && pasDef[i].nSize == 4)
    2154                 :         {
    2155                 :             /*---------------------------------------------------------
    2156                 :              * Single precision floats
    2157                 :              *--------------------------------------------------------*/
    2158               0 :             AVCRawBinWriteFloat(psFile, pasFields[i].fFloat);
    2159                 :         }
    2160               0 :         else if (nType == AVC_FT_BINFLOAT && pasDef[i].nSize == 8)
    2161                 :         {
    2162                 :             /*---------------------------------------------------------
    2163                 :              * Double precision floats
    2164                 :              *--------------------------------------------------------*/
    2165               0 :             AVCRawBinWriteDouble(psFile, pasFields[i].dDouble);
    2166                 :         }
    2167                 :         else
    2168                 :         {
    2169                 :             /*---------------------------------------------------------
    2170                 :              * Hummm... unsupported field type...
    2171                 :              *--------------------------------------------------------*/
    2172               0 :             CPLError(CE_Failure, CPLE_NotSupported,
    2173                 :                      "Unsupported field type in %s: (type=%d, size=%d)",
    2174               0 :                      pszFname, nType, pasDef[i].nSize);
    2175               0 :             return -1;
    2176                 :         }
    2177                 : 
    2178               0 :         nBytesWritten += pasDef[i].nSize;
    2179                 :     }
    2180                 : 
    2181                 :     /*-----------------------------------------------------------------
    2182                 :      * Record size is rounded to a multiple of 2 bytes.
    2183                 :      * Check the number of bytes written, and pad with zeros if 
    2184                 :      * necessary.
    2185                 :      *----------------------------------------------------------------*/
    2186               0 :     nRecordSize = ((nRecordSize+1)/2)*2;
    2187               0 :     if (nBytesWritten < nRecordSize)
    2188               0 :         AVCRawBinWriteZeros(psFile, nRecordSize - nBytesWritten);
    2189                 : 
    2190               0 :     if (CPLGetLastErrorNo() != 0)
    2191               0 :         return -1;
    2192                 : 
    2193               0 :     return 0;
    2194                 : }
    2195                 : 
    2196                 : /**********************************************************************
    2197                 :  *                          _AVCBinWriteDBFTableRec()
    2198                 :  *
    2199                 :  * (This function is for internal library use... external calls should
    2200                 :  * go to AVCBinWriteTableRec() instead)
    2201                 :  *
    2202                 :  * Write a table data record at the current position in DBF file.
    2203                 :  *
    2204                 :  * The contents of the pasDef and pasFields structures is assumed to 
    2205                 :  * be valid... this function performs no validation on the consistency 
    2206                 :  * of what it is given as input.
    2207                 :  *
    2208                 :  * Returns 0 on success or -1 on error.
    2209                 :  **********************************************************************/
    2210               0 : int _AVCBinWriteDBFTableRec(DBFHandle hDBFFile, int nFields,
    2211                 :                             AVCFieldInfo *pasDef, AVCField *pasFields,
    2212                 :                             int *nCurDBFRecord, const char *pszFname)
    2213                 : {
    2214               0 :     int i, nType, nStatus = FALSE;
    2215                 : 
    2216               0 :     if (hDBFFile == NULL)
    2217               0 :         return -1;
    2218                 : 
    2219               0 :     (*nCurDBFRecord)++;
    2220                 : 
    2221               0 :     for(i=0; i<nFields; i++)
    2222                 :     {
    2223               0 :         if (CPLGetLastErrorNo() != 0)
    2224               0 :             return -1;
    2225                 : 
    2226               0 :         nType = pasDef[i].nType1*10;
    2227                 : 
    2228               0 :         if (nType ==  AVC_FT_DATE || nType == AVC_FT_CHAR)
    2229                 :         {
    2230                 :             /*---------------------------------------------------------
    2231                 :              * Values stored as strings
    2232                 :              *--------------------------------------------------------*/
    2233               0 :             nStatus = DBFWriteStringAttribute(hDBFFile, *nCurDBFRecord, i, 
    2234               0 :                                               (char *)pasFields[i].pszStr);
    2235                 :         }
    2236               0 :         else if (nType == AVC_FT_FIXINT || nType == AVC_FT_FIXNUM)
    2237                 :         {
    2238                 :             /*---------------------------------------------------------
    2239                 :              * Numbers stored as strings
    2240                 :              *--------------------------------------------------------*/
    2241               0 :             nStatus = DBFWriteAttributeDirectly(hDBFFile, *nCurDBFRecord, i, 
    2242               0 :                                                 pasFields[i].pszStr);
    2243                 :         }
    2244               0 :         else if (nType == AVC_FT_BININT && pasDef[i].nSize == 4)
    2245                 :         {
    2246                 :             /*---------------------------------------------------------
    2247                 :              * 32 bit binary integers
    2248                 :              *--------------------------------------------------------*/
    2249               0 :             nStatus = DBFWriteIntegerAttribute(hDBFFile, *nCurDBFRecord, i, 
    2250               0 :                                                pasFields[i].nInt32);
    2251                 :         }
    2252               0 :         else if (nType == AVC_FT_BININT && pasDef[i].nSize == 2)
    2253                 :         {
    2254                 :             /*---------------------------------------------------------
    2255                 :              * 16 bit binary integers
    2256                 :              *--------------------------------------------------------*/
    2257               0 :             nStatus = DBFWriteIntegerAttribute(hDBFFile, *nCurDBFRecord, i, 
    2258               0 :                                                pasFields[i].nInt16);
    2259                 :         }
    2260               0 :         else if (nType == AVC_FT_BINFLOAT)
    2261                 :         {
    2262                 :             /*---------------------------------------------------------
    2263                 :              * Single+double precision floats
    2264                 :              *--------------------------------------------------------*/
    2265               0 :             char szBuf[32] = "";
    2266                 :             int nLen;
    2267                 : 
    2268               0 :             if (pasDef[i].nSize == 4)
    2269               0 :                 nLen = AVCPrintRealValue(szBuf, AVC_FORMAT_DBF_FLOAT,
    2270               0 :                                          AVCFileTABLE, pasFields[i].fFloat);
    2271                 :             else
    2272               0 :                 nLen = AVCPrintRealValue(szBuf, AVC_FORMAT_DBF_FLOAT,
    2273               0 :                                          AVCFileTABLE, pasFields[i].dDouble);
    2274                 : 
    2275               0 :             szBuf[nLen] = '\0';
    2276                 : 
    2277               0 :             nStatus = DBFWriteAttributeDirectly(hDBFFile, *nCurDBFRecord, i, 
    2278                 :                                                 szBuf);
    2279                 :         }
    2280                 :         else
    2281                 :         {
    2282                 :             /*---------------------------------------------------------
    2283                 :              * Hummm... unsupported field type...
    2284                 :              *--------------------------------------------------------*/
    2285               0 :             CPLError(CE_Failure, CPLE_NotSupported,
    2286                 :                      "Unsupported field type in %s: (type=%d, size=%d)",
    2287               0 :                      pszFname, nType, pasDef[i].nSize);
    2288               0 :             return -1;
    2289                 :         }
    2290                 : 
    2291               0 :         if (nStatus != TRUE)
    2292                 :         {
    2293               0 :             CPLError(CE_Failure, CPLE_FileIO,
    2294                 :                      "Failed writing table field %d to record %d in %s",
    2295                 :                      i, *nCurDBFRecord, pszFname);
    2296               0 :             return -1;
    2297                 :         }
    2298                 : 
    2299                 :     }
    2300                 : 
    2301               0 :     return 0;
    2302                 : }
    2303                 : 
    2304                 : /**********************************************************************
    2305                 :  *                          AVCBinWriteTableRec()
    2306                 :  *
    2307                 :  * Write a table data record at the current position in file.
    2308                 :  *
    2309                 :  * The contents of the pasDef and pasFields structures is assumed to 
    2310                 :  * be valid... this function performs no validation on the consistency 
    2311                 :  * of what it is given as input.
    2312                 :  *
    2313                 :  * Returns 0 on success or -1 on error.
    2314                 :  *
    2315                 :  * If a problem happens, then CPLError() will be called by the lower-level
    2316                 :  * functions and CPLGetLastErrorNo() can be used to find out what happened.
    2317                 :  **********************************************************************/
    2318               0 : int AVCBinWriteTableRec(AVCBinFile *psFile, AVCField *pasFields)
    2319                 : {
    2320               0 :     if (psFile->eFileType != AVCFileTABLE||
    2321               0 :         psFile->hdr.psTableDef->numRecords == 0)
    2322               0 :         return -1;
    2323                 : 
    2324               0 :     if (psFile->eCoverType == AVCCoverPC || psFile->eCoverType == AVCCoverPC2)
    2325               0 :         return _AVCBinWriteDBFTableRec(psFile->hDBFFile, 
    2326               0 :                                        psFile->hdr.psTableDef->numFields,
    2327               0 :                                        psFile->hdr.psTableDef->pasFieldDef,
    2328                 :                                        pasFields,
    2329                 :                                        &(psFile->nCurDBFRecord),
    2330               0 :                                        psFile->pszFilename);
    2331                 :     else
    2332               0 :         return _AVCBinWriteTableRec(psFile->psRawBinFile, 
    2333               0 :                                     psFile->hdr.psTableDef->numFields,
    2334               0 :                                     psFile->hdr.psTableDef->pasFieldDef,
    2335                 :                                     pasFields,
    2336               0 :                                     psFile->hdr.psTableDef->nRecSize,
    2337               0 :                                     psFile->pszFilename);
    2338                 : }
    2339                 : 

Generated by: LCOV version 1.7