LTP GCOV extension - code coverage report
Current view: directory - ogr/ogrsf_frmts/avc - avc_e00gen.c
Test: gdal_filtered.info
Date: 2010-07-12 Instrumented lines: 343
Code covered: 3.2 % Executed lines: 11

       1                 : /**********************************************************************
       2                 :  * $Id: avc_e00gen.c,v 1.18 2008/07/23 20:51:38 dmorissette Exp $
       3                 :  *
       4                 :  * Name:     avc_e00gen.c
       5                 :  * Project:  Arc/Info vector coverage (AVC)  BIN->E00 conversion library
       6                 :  * Language: ANSI C
       7                 :  * Purpose:  Functions to generate ASCII E00 lines form binary structures.
       8                 :  * Author:   Daniel Morissette, dmorissette@dmsolutions.ca
       9                 :  *
      10                 :  **********************************************************************
      11                 :  * Copyright (c) 1999-2005, Daniel Morissette
      12                 :  *
      13                 :  * Permission is hereby granted, free of charge, to any person obtaining a
      14                 :  * copy of this software and associated documentation files (the "Software"),
      15                 :  * to deal in the Software without restriction, including without limitation
      16                 :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      17                 :  * and/or sell copies of the Software, and to permit persons to whom the
      18                 :  * Software is furnished to do so, subject to the following conditions:
      19                 :  * 
      20                 :  * The above copyright notice and this permission notice shall be included
      21                 :  * in all copies or substantial portions of the Software.
      22                 :  * 
      23                 :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      24                 :  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      25                 :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
      26                 :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      27                 :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      28                 :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
      29                 :  * DEALINGS IN THE SOFTWARE.
      30                 :  **********************************************************************
      31                 :  *
      32                 :  * $Log: avc_e00gen.c,v $
      33                 :  * Revision 1.18  2008/07/23 20:51:38  dmorissette
      34                 :  * Fixed GCC 4.1.x compile warnings related to use of char vs unsigned char
      35                 :  * (GDAL/OGR ticket http://trac.osgeo.org/gdal/ticket/2495)
      36                 :  *
      37                 :  * Revision 1.17  2006/06/14 15:01:33  daniel
      38                 :  * Remove any embeded '\0' from data line in AVCE00GenTableRec()
      39                 :  *
      40                 :  * Revision 1.16  2005/06/03 03:49:58  daniel
      41                 :  * Update email address, website url, and copyright dates
      42                 :  *
      43                 :  * Revision 1.15  2004/08/19 17:48:20  warmerda
      44                 :  * Avoid uninitialized variable warnings.
      45                 :  *
      46                 :  * Revision 1.14  2001/11/25 21:15:23  daniel
      47                 :  * Added hack (AVC_MAP_TYPE40_TO_DOUBLE) to map type 40 fields bigger than 8
      48                 :  * digits to double precision as we generate E00 output (bug599)
      49                 :  *
      50                 :  * Revision 1.13  2001/11/19 20:39:48  daniel
      51                 :  * Change to correctly format 0-arc PAL records, so that they have a
      52                 :  * single "filler" arc record
      53                 :  *
      54                 :  * Revision 1.12  2000/09/26 20:21:04  daniel
      55                 :  * Added AVCCoverPC write
      56                 :  *
      57                 :  * Revision 1.11  2000/09/22 19:45:20  daniel
      58                 :  * Switch to MIT-style license
      59                 :  *
      60                 :  * Revision 1.10  2000/02/04 04:54:03  daniel
      61                 :  * Fixed warnings
      62                 :  *
      63                 :  * Revision 1.9  2000/02/03 07:21:02  daniel
      64                 :  * TXT/TX6 with string longer than 80 chars: split string in 80 chars chunks
      65                 :  *
      66                 :  * Revision 1.8  2000/02/02 04:28:00  daniel
      67                 :  * Fixed support of TX6/RXP/RPL coming from "weird" coverages
      68                 :  *
      69                 :  * Revision 1.7  1999/08/23 18:20:49  daniel
      70                 :  * Fixed support for attribute fields type 40
      71                 :  *
      72                 :  * Revision 1.6  1999/05/17 16:19:39  daniel
      73                 :  * Made sure ACVE00GenTableRec() removes all spaces at the end of a
      74                 :  * table record line (it used to leave one space)
      75                 :  *
      76                 :  * Revision 1.5  1999/05/11 02:08:17  daniel
      77                 :  * Simple changes related to the addition of coverage write support.
      78                 :  *
      79                 :  * Revision 1.4  1999/03/03 02:06:38  daniel
      80                 :  * Properly handle 8 bytes floats inside single precision tables.
      81                 :  *
      82                 :  * Revision 1.3  1999/02/25 17:01:58  daniel
      83                 :  * Added support for 16 bit integers in INFO tables (type=50, size=2)
      84                 :  *
      85                 :  * Revision 1.2  1999/02/25 04:17:51  daniel
      86                 :  * Added TXT, TX6/TX7, RXP and RPL support + some minor changes
      87                 :  *
      88                 :  * Revision 1.1  1999/01/29 16:28:52  daniel
      89                 :  * Initial revision
      90                 :  *
      91                 :  **********************************************************************/
      92                 : 
      93                 : #include "avc.h"
      94                 : 
      95                 : #include <ctype.h>      /* toupper() */
      96                 : 
      97                 : /**********************************************************************
      98                 :  *                          AVCE00GenInfoAlloc()
      99                 :  *
     100                 :  * Allocate and initialize a new AVCE00GenInfo structure.
     101                 :  *
     102                 :  * The structure will eventually have to be freed with AVCE00GenInfoFree().
     103                 :  **********************************************************************/
     104                 : AVCE00GenInfo  *AVCE00GenInfoAlloc(int nCoverPrecision)
     105               1 : {
     106                 :     AVCE00GenInfo       *psInfo;
     107                 : 
     108               1 :     psInfo = (AVCE00GenInfo*)CPLCalloc(1,sizeof(AVCE00GenInfo));
     109                 : 
     110                 :     /* Allocate output buffer.  
     111                 :      * 2k should be enough... the biggest thing we'll need to store
     112                 :      * in it will be 1 complete INFO table record.
     113                 :      */
     114               1 :     psInfo->nBufSize = 2048;
     115               1 :     psInfo->pszBuf = (char *)CPLMalloc(psInfo->nBufSize*sizeof(char));
     116                 : 
     117               1 :     psInfo->nPrecision = nCoverPrecision;
     118                 : 
     119               1 :     return psInfo;
     120                 : }
     121                 : 
     122                 : /**********************************************************************
     123                 :  *                          AVCE00GenInfoFree()
     124                 :  *
     125                 :  * Free any memory associated with a AVCE00GenInfo structure.
     126                 :  **********************************************************************/
     127                 : void    AVCE00GenInfoFree(AVCE00GenInfo  *psInfo)
     128               1 : {
     129               1 :     if (psInfo)
     130               1 :         CPLFree(psInfo->pszBuf);
     131               1 :     CPLFree(psInfo);
     132               1 : }
     133                 : 
     134                 : 
     135                 : /**********************************************************************
     136                 :  *                          AVCE00GenReset()
     137                 :  *
     138                 :  * Reset the fields in the AVCE00GenInfo structure so that further calls
     139                 :  * with bCont = TRUE (ex: AVCE00GenArc(psInfo, TRUE)) would return NULL.
     140                 :  **********************************************************************/
     141                 : void    AVCE00GenReset(AVCE00GenInfo  *psInfo)
     142               0 : {
     143                 :     /* Reinitialize counters so that further calls with bCont = TRUE,
     144                 :      * like AVCE00GenArc(psInfo, TRUE) would return NULL.
     145                 :      */
     146               0 :     psInfo->iCurItem = psInfo->numItems = 0;
     147               0 : }
     148                 : 
     149                 : /**********************************************************************
     150                 :  *                          AVCE00GenStartSection()
     151                 :  *
     152                 :  * Generate the first line of an E00 section.
     153                 :  *
     154                 :  * pszClassName applies only to JABBERWOCKY type of sections.
     155                 :  **********************************************************************/
     156                 : const char *AVCE00GenStartSection(AVCE00GenInfo *psInfo, AVCFileType eType, 
     157                 :                                   const char *pszClassName)
     158               0 : {
     159               0 :     char *pszName = "UNK";
     160                 : 
     161               0 :     AVCE00GenReset(psInfo);
     162                 : 
     163               0 :     if (eType == AVCFileTX6 || eType == AVCFileRXP || eType == AVCFileRPL)
     164                 :     {
     165                 :         /* TX6/RXP/RPL sections start with the class name (the basename 
     166                 :          * of the file) in uppercase.
     167                 :          * ex:  The section for "cities.txt" would start with "CITIES"
     168                 :          */
     169                 :         int i;
     170               0 :         for(i=0; pszClassName[i] != '\0'; i++)
     171                 :         {
     172               0 :             psInfo->pszBuf[i] = toupper(pszClassName[i]);
     173                 :         }
     174               0 :         psInfo->pszBuf[i] = '\0';
     175                 :     }
     176                 :     else
     177                 :     {
     178                 :         /* In most cases, the section starts with a 3 letters code followed
     179                 :          * by the precision code (2 or 3)
     180                 :          */
     181               0 :         switch(eType)
     182                 :         {
     183                 :           case AVCFileARC:
     184               0 :             pszName = "ARC";
     185               0 :             break;
     186                 :           case AVCFilePAL:
     187               0 :             pszName = "PAL";
     188               0 :             break;
     189                 :           case AVCFileCNT:
     190               0 :             pszName = "CNT";
     191               0 :             break;
     192                 :           case AVCFileLAB:
     193               0 :             pszName = "LAB";
     194               0 :             break;
     195                 :           case AVCFileTOL:
     196               0 :             pszName = "TOL";
     197               0 :             break;
     198                 :           case AVCFilePRJ:
     199               0 :             pszName = "PRJ";
     200               0 :             break;
     201                 :           case AVCFileTXT:
     202               0 :             pszName = "TXT";
     203               0 :             break;
     204                 :           default:
     205               0 :             CPLError(CE_Failure, CPLE_NotSupported,
     206                 :                      "Unsupported E00 section type!");
     207                 :         }
     208                 : 
     209               0 :         if (psInfo->nPrecision == AVC_DOUBLE_PREC)
     210               0 :             sprintf(psInfo->pszBuf, "%s  3", pszName);
     211                 :         else
     212               0 :             sprintf(psInfo->pszBuf, "%s  2", pszName);
     213                 :     }
     214                 : 
     215               0 :     return psInfo->pszBuf;
     216                 : }
     217                 : 
     218                 : /**********************************************************************
     219                 :  *                          AVCE00GenEndSection()
     220                 :  *
     221                 :  * Generate the last line(s) of an E00 section.
     222                 :  *
     223                 :  * This function should be called once with bCont=FALSE to get the
     224                 :  * first "end of section" line for the current section, and then call 
     225                 :  * with bCont=TRUE to get all the other lines.
     226                 :  *
     227                 :  * The function returns NULL when there are no more lines to generate
     228                 :  * for this "end of section".
     229                 :  **********************************************************************/
     230                 : const char *AVCE00GenEndSection(AVCE00GenInfo *psInfo, AVCFileType eType,
     231                 :                                 GBool bCont)
     232               0 : {
     233               0 :     if (bCont == FALSE)
     234                 :     {
     235                 :         /*------------------------------------------------------------- 
     236                 :          * Most section types end with only 1 line.
     237                 :          *------------------------------------------------------------*/
     238               0 :         AVCE00GenReset(psInfo);
     239               0 :         psInfo->iCurItem = 0;
     240                 : 
     241               0 :         if (eType == AVCFileARC ||
     242                 :             eType == AVCFilePAL ||
     243                 :             eType == AVCFileRPL ||
     244                 :             eType == AVCFileCNT ||
     245                 :             eType == AVCFileTOL ||
     246                 :             eType == AVCFileTXT ||
     247                 :             eType == AVCFileTX6 )
     248                 :         {
     249               0 :             sprintf(psInfo->pszBuf, 
     250                 :     "        -1         0         0         0         0         0         0");
     251                 :         }
     252               0 :         else if (eType == AVCFileLAB)
     253                 :         {
     254               0 :             if (psInfo->nPrecision == AVC_DOUBLE_PREC)
     255               0 :                 sprintf(psInfo->pszBuf, 
     256                 :           "        -1         0 0.00000000000000E+00 0.00000000000000E+00");
     257                 :             else
     258               0 :                 sprintf(psInfo->pszBuf, 
     259                 :           "        -1         0 0.0000000E+00 0.0000000E+00");
     260                 :         }
     261               0 :         else if (eType == AVCFilePRJ)
     262                 :         {
     263               0 :             sprintf(psInfo->pszBuf, "EOP");
     264                 :         }
     265               0 :         else if (eType == AVCFileRXP )
     266                 :         {
     267               0 :             sprintf(psInfo->pszBuf,"        -1         0");
     268                 :         }
     269                 :         else
     270                 :         {
     271               0 :             CPLError(CE_Failure, CPLE_NotSupported,
     272                 :                      "Unsupported E00 section type!");
     273               0 :             return NULL;
     274                 :         }
     275                 :     }
     276               0 :     else if ( psInfo->iCurItem == 0 &&
     277                 :               psInfo->nPrecision == AVC_DOUBLE_PREC &&
     278                 :               (eType == AVCFilePAL || eType == AVCFileRPL)     )
     279                 :     {
     280                 :         /*--------------------------------------------------------- 
     281                 :          * Return the 2nd line for the end of a PAL or RPL section.
     282                 :          *--------------------------------------------------------*/
     283               0 :         sprintf(psInfo->pszBuf, 
     284                 :                 " 0.00000000000000E+00 0.00000000000000E+00");
     285                 : 
     286               0 :         psInfo->iCurItem++;
     287                 :     }
     288                 :     else
     289                 :     {
     290                 :         /*----------------------------------------------------- 
     291                 :          * All other section types end with only one line, and thus
     292                 :          * we return NULL when bCont==TRUE
     293                 :          *----------------------------------------------------*/
     294               0 :         return NULL;
     295                 :     }
     296                 : 
     297               0 :     return psInfo->pszBuf;
     298                 : }
     299                 : 
     300                 : 
     301                 : /**********************************************************************
     302                 :  *                          AVCE00GenObject()
     303                 :  *
     304                 :  * Cover function on top of AVCE00GenArc/Pal/Cnt/Lab() that will
     305                 :  * call the right function according to argument eType.
     306                 :  *
     307                 :  * Since there is no compiler type checking on psObj, you have to
     308                 :  * be very careful to make sure you pass an object of the right type 
     309                 :  * when you use this function!
     310                 :  *
     311                 :  * The function returns NULL when there are no more lines to generate
     312                 :  * for this ARC.
     313                 :  **********************************************************************/
     314                 : const char *AVCE00GenObject(AVCE00GenInfo *psInfo, 
     315                 :                             AVCFileType eType, void *psObj, GBool bCont)
     316               0 : {
     317               0 :     const char *pszLine = NULL;
     318                 : 
     319               0 :     switch(eType)
     320                 :     {
     321                 :       case AVCFileARC:
     322               0 :         pszLine = AVCE00GenArc(psInfo, (AVCArc*)psObj, bCont);
     323               0 :         break;
     324                 :       case AVCFilePAL:
     325                 :       case AVCFileRPL:
     326               0 :         pszLine = AVCE00GenPal(psInfo, (AVCPal*)psObj, bCont);
     327               0 :         break;
     328                 :       case AVCFileCNT:
     329               0 :         pszLine = AVCE00GenCnt(psInfo, (AVCCnt*)psObj, bCont);
     330               0 :         break;
     331                 :       case AVCFileLAB:
     332               0 :         pszLine = AVCE00GenLab(psInfo, (AVCLab*)psObj, bCont);
     333               0 :         break;
     334                 :       case AVCFileTOL:
     335               0 :         pszLine = AVCE00GenTol(psInfo, (AVCTol*)psObj, bCont);
     336               0 :         break;
     337                 :       case AVCFileTXT:
     338               0 :         pszLine = AVCE00GenTxt(psInfo, (AVCTxt*)psObj, bCont);
     339               0 :         break;
     340                 :       case AVCFileTX6:
     341               0 :         pszLine = AVCE00GenTx6(psInfo, (AVCTxt*)psObj, bCont);
     342               0 :         break;
     343                 :       case AVCFilePRJ:
     344               0 :         pszLine = AVCE00GenPrj(psInfo, (char**)psObj, bCont);
     345               0 :         break;
     346                 :       case AVCFileRXP:
     347               0 :         pszLine = AVCE00GenRxp(psInfo, (AVCRxp*)psObj, bCont);
     348               0 :         break;
     349                 :       default:
     350               0 :         CPLError(CE_Failure, CPLE_NotSupported,
     351                 :                  "AVCE00GenObject(): Unsupported file type!");
     352                 :     }
     353                 : 
     354               0 :     return pszLine;
     355                 : }
     356                 : 
     357                 : 
     358                 : /*=====================================================================
     359                 :                             ARC stuff
     360                 :  =====================================================================*/
     361                 : 
     362                 : /**********************************************************************
     363                 :  *                          AVCE00GenArc()
     364                 :  *
     365                 :  * Generate the next line of an E00 ARC.
     366                 :  *
     367                 :  * This function should be called once with bCont=FALSE to get the
     368                 :  * first E00 line for the current ARC, and then call with bCont=TRUE
     369                 :  * to get all the other lines for this ARC.
     370                 :  *
     371                 :  * The function returns NULL when there are no more lines to generate
     372                 :  * for this ARC.
     373                 :  **********************************************************************/
     374                 : const char *AVCE00GenArc(AVCE00GenInfo *psInfo, AVCArc *psArc, GBool bCont)
     375               0 : {
     376               0 :     if (bCont == FALSE)
     377                 :     {
     378                 :         /* Initialize the psInfo structure with info about the
     379                 :          * current ARC.
     380                 :          */
     381               0 :         psInfo->iCurItem = 0;
     382               0 :         if (psInfo->nPrecision == AVC_DOUBLE_PREC)
     383               0 :             psInfo->numItems = psArc->numVertices;
     384                 :         else
     385               0 :             psInfo->numItems = (psArc->numVertices+1)/2;
     386                 : 
     387                 :         /* And return the ARC header line
     388                 :          */
     389               0 :         sprintf(psInfo->pszBuf, "%10d%10d%10d%10d%10d%10d%10d",
     390                 :                 psArc->nArcId, psArc->nUserId,
     391                 :                 psArc->nFNode, psArc->nTNode,
     392                 :                 psArc->nLPoly, psArc->nRPoly,
     393                 :                 psArc->numVertices);
     394                 :     }
     395               0 :     else if (psInfo->iCurItem < psInfo->numItems)
     396                 :     {
     397                 :         int iVertex;
     398                 : 
     399                 :         /* return the next set of vertices for the ARC.
     400                 :          */
     401               0 :         if (psInfo->nPrecision == AVC_DOUBLE_PREC)
     402                 :         {
     403               0 :             iVertex = psInfo->iCurItem;
     404                 : 
     405               0 :             psInfo->pszBuf[0] = '\0';
     406               0 :             AVCPrintRealValue(psInfo->pszBuf, psInfo->nPrecision, AVCFileARC,
     407                 :                             psArc->pasVertices[iVertex].x);
     408               0 :             AVCPrintRealValue(psInfo->pszBuf, psInfo->nPrecision, AVCFileARC,
     409                 :                             psArc->pasVertices[iVertex].y);
     410                 :         }
     411                 :         else
     412                 :         {
     413               0 :             iVertex = psInfo->iCurItem*2;
     414                 : 
     415               0 :             psInfo->pszBuf[0] = '\0';
     416               0 :             AVCPrintRealValue(psInfo->pszBuf, psInfo->nPrecision, AVCFileARC,
     417                 :                             psArc->pasVertices[iVertex].x);
     418               0 :             AVCPrintRealValue(psInfo->pszBuf, psInfo->nPrecision, AVCFileARC,
     419                 :                             psArc->pasVertices[iVertex].y);
     420                 : 
     421                 :             /* Check because if we have a odd number of vertices then
     422                 :              * the last line contains only one pair of vertices.
     423                 :              */
     424               0 :             if (iVertex+1 < psArc->numVertices)
     425                 :             {
     426               0 :                 AVCPrintRealValue(psInfo->pszBuf,psInfo->nPrecision,AVCFileARC,
     427                 :                                 psArc->pasVertices[iVertex+1].x);
     428               0 :                 AVCPrintRealValue(psInfo->pszBuf,psInfo->nPrecision,AVCFileARC,
     429                 :                                 psArc->pasVertices[iVertex+1].y);
     430                 :             }
     431                 :         }
     432               0 :         psInfo->iCurItem++;
     433                 :     }
     434                 :     else
     435                 :     {
     436                 :         /* No more lines to generate for this ARC.
     437                 :          */
     438               0 :         return NULL;
     439                 :     }
     440                 : 
     441               0 :     return psInfo->pszBuf;
     442                 : }
     443                 : 
     444                 : /*=====================================================================
     445                 :                             PAL stuff
     446                 :  =====================================================================*/
     447                 : 
     448                 : /**********************************************************************
     449                 :  *                          AVCE00GenPal()
     450                 :  *
     451                 :  * Generate the next line of an E00 PAL (Polygon Arc List) entry.
     452                 :  *
     453                 :  * This function should be called once with bCont=FALSE to get the
     454                 :  * first E00 line for the current PAL, and then call with bCont=TRUE
     455                 :  * to get all the other lines for this PAL.
     456                 :  *
     457                 :  * The function returns NULL when there are no more lines to generate
     458                 :  * for this PAL entry.
     459                 :  **********************************************************************/
     460                 : const char *AVCE00GenPal(AVCE00GenInfo *psInfo, AVCPal *psPal, GBool bCont)
     461               0 : {
     462               0 :     if (bCont == FALSE)
     463                 :     {
     464                 :         /* Initialize the psInfo structure with info about the
     465                 :          * current PAL.  (Number of lines excluding header)
     466                 :          */
     467               0 :         psInfo->numItems = (psPal->numArcs+1)/2;
     468                 : 
     469                 : 
     470                 :         /* And return the PAL header line.
     471                 :          */
     472               0 :         sprintf(psInfo->pszBuf, "%10d", psPal->numArcs);
     473                 : 
     474               0 :         AVCPrintRealValue(psInfo->pszBuf, psInfo->nPrecision, AVCFilePAL,
     475                 :                         psPal->sMin.x);
     476               0 :         AVCPrintRealValue(psInfo->pszBuf, psInfo->nPrecision, AVCFilePAL,
     477                 :                         psPal->sMin.y);
     478                 : 
     479                 :         /* Double precision PAL entries have their header on 2 lines!
     480                 :          */
     481               0 :         if (psInfo->nPrecision == AVC_DOUBLE_PREC)
     482                 :         {
     483               0 :             psInfo->iCurItem = -1;      /* Means 1 line left in header */
     484                 :         }
     485                 :         else
     486                 :         {
     487               0 :             AVCPrintRealValue(psInfo->pszBuf, psInfo->nPrecision, AVCFilePAL,
     488                 :                             psPal->sMax.x);
     489               0 :             AVCPrintRealValue(psInfo->pszBuf, psInfo->nPrecision, AVCFilePAL,
     490                 :                             psPal->sMax.y);
     491               0 :             psInfo->iCurItem = 0;       /* Next thing = first Arc entry */
     492                 :         }
     493                 : 
     494                 :     }
     495               0 :     else if (psInfo->iCurItem == -1)
     496                 :     {
     497                 :         /* Second (and last) header line for double precision coverages
     498                 :          */
     499               0 :         psInfo->pszBuf[0] = '\0';
     500               0 :         AVCPrintRealValue(psInfo->pszBuf, psInfo->nPrecision, AVCFilePAL,
     501                 :                         psPal->sMax.x);
     502               0 :         AVCPrintRealValue(psInfo->pszBuf, psInfo->nPrecision, AVCFilePAL,
     503                 :                         psPal->sMax.y);
     504                 : 
     505               0 :         if ( psInfo->numItems == 0 )
     506                 :         {
     507               0 :            psInfo->iCurItem = -2;      /* We have a 0-arc polygon, which needs
     508                 :                                           an arc list with one "0 0 0" element */
     509                 :         }
     510                 :         else
     511                 :         {
     512               0 :            psInfo->iCurItem = 0;       /* Next thing = first Arc entry */
     513                 :         }
     514                 :     }
     515               0 :     else if (psInfo->iCurItem == -2)
     516                 :     {
     517               0 :         sprintf(psInfo->pszBuf, "%10d%10d%10d", 0, 0, 0);
     518               0 :         psInfo->iCurItem = 0;       /* Next thing = first Arc entry */
     519                 :     }
     520               0 :     else if (psInfo->iCurItem < psInfo->numItems)
     521                 :     {
     522                 :         /* Return PAL Arc entries...
     523                 :          */
     524                 :         int iArc;
     525                 : 
     526               0 :         iArc = psInfo->iCurItem*2;
     527                 : 
     528                 :         /* If we have a odd number of arcs then
     529                 :          * the last line contains only one arc entry.
     530                 :          */
     531               0 :         if (iArc+1 < psPal->numArcs)
     532                 :         {
     533               0 :             sprintf(psInfo->pszBuf, "%10d%10d%10d%10d%10d%10d",
     534                 :                                     psPal->pasArcs[iArc].nArcId,
     535                 :                                     psPal->pasArcs[iArc].nFNode,
     536                 :                                     psPal->pasArcs[iArc].nAdjPoly,
     537                 :                                     psPal->pasArcs[iArc+1].nArcId,
     538                 :                                     psPal->pasArcs[iArc+1].nFNode,
     539                 :                                     psPal->pasArcs[iArc+1].nAdjPoly);
     540                 : 
     541                 :         }
     542                 :         else
     543                 :         {
     544               0 :             sprintf(psInfo->pszBuf, "%10d%10d%10d", 
     545                 :                                     psPal->pasArcs[iArc].nArcId,
     546                 :                                     psPal->pasArcs[iArc].nFNode,
     547                 :                                     psPal->pasArcs[iArc].nAdjPoly);
     548                 :         }
     549               0 :         psInfo->iCurItem++;
     550                 :     }
     551                 :     else
     552                 :     {
     553                 :         /* No more lines to generate for this PAL.
     554                 :          */
     555               0 :         return NULL;
     556                 :     }
     557                 : 
     558               0 :     return psInfo->pszBuf;
     559                 : }
     560                 : 
     561                 : 
     562                 : /*=====================================================================
     563                 :                             CNT stuff
     564                 :  =====================================================================*/
     565                 : 
     566                 : /**********************************************************************
     567                 :  *                          AVCE00GenCnt()
     568                 :  *
     569                 :  * Generate the next line of an E00 CNT (Polygon Centroid) entry.
     570                 :  *
     571                 :  * This function should be called once with bCont=FALSE to get the
     572                 :  * first E00 line for the current CNT, and then call with bCont=TRUE
     573                 :  * to get all the other lines for this CNT.
     574                 :  *
     575                 :  * The function returns NULL when there are no more lines to generate
     576                 :  * for this CNT entry.
     577                 :  **********************************************************************/
     578                 : const char *AVCE00GenCnt(AVCE00GenInfo *psInfo, AVCCnt *psCnt, GBool bCont)
     579               0 : {
     580               0 :     if (bCont == FALSE)
     581                 :     {
     582                 :         /* Initialize the psInfo structure with info about the
     583                 :          * current CNT.
     584                 :          */
     585               0 :         psInfo->iCurItem = 0;
     586               0 :         psInfo->numItems = (psCnt->numLabels+7)/8;
     587                 : 
     588                 :         /* And return the CNT header line.
     589                 :          */
     590               0 :         sprintf(psInfo->pszBuf, "%10d", psCnt->numLabels);
     591                 : 
     592               0 :         AVCPrintRealValue(psInfo->pszBuf, psInfo->nPrecision, AVCFileCNT,
     593                 :                         psCnt->sCoord.x);
     594               0 :         AVCPrintRealValue(psInfo->pszBuf, psInfo->nPrecision, AVCFileCNT,
     595                 :                         psCnt->sCoord.y);
     596                 : 
     597                 :     }
     598               0 :     else if (psInfo->iCurItem < psInfo->numItems)
     599                 :     {
     600                 :         /* Return CNT Label Ids, 8 label Ids per line... 
     601                 :          */
     602                 :         int i, nFirstLabel, numLabels;
     603                 : 
     604               0 :         nFirstLabel = psInfo->iCurItem * 8;
     605               0 :         numLabels = MIN(8, (psCnt->numLabels-nFirstLabel));
     606                 : 
     607               0 :         psInfo->pszBuf[0] = '\0';
     608               0 :         for(i=0; i < numLabels; i++)
     609                 :         {
     610               0 :             sprintf(psInfo->pszBuf + strlen(psInfo->pszBuf), "%10d", 
     611                 :                                         psCnt->panLabelIds[nFirstLabel+i] );
     612                 :         }
     613                 : 
     614               0 :         psInfo->iCurItem++;
     615                 :     }
     616                 :     else
     617                 :     {
     618                 :         /* No more lines to generate for this CNT.
     619                 :          */
     620               0 :         return NULL;
     621                 :     }
     622                 : 
     623               0 :     return psInfo->pszBuf;
     624                 : }
     625                 : 
     626                 : 
     627                 : /*=====================================================================
     628                 :                             LAB stuff
     629                 :  =====================================================================*/
     630                 : 
     631                 : /**********************************************************************
     632                 :  *                          AVCE00GenLab()
     633                 :  *
     634                 :  * Generate the next line of an E00 LAB (Label) entry.
     635                 :  *
     636                 :  * This function should be called once with bCont=FALSE to get the
     637                 :  * first E00 line for the current LAB, and then call with bCont=TRUE
     638                 :  * to get all the other lines for this LAB.
     639                 :  *
     640                 :  * The function returns NULL when there are no more lines to generate
     641                 :  * for this LAB entry.
     642                 :  **********************************************************************/
     643                 : const char *AVCE00GenLab(AVCE00GenInfo *psInfo, AVCLab *psLab, GBool bCont)
     644               0 : {
     645               0 :     if (bCont == FALSE)
     646                 :     {
     647                 :         /* Initialize the psInfo structure with info about the
     648                 :          * current LAB. (numItems = Number of lines excluding header)
     649                 :          */
     650               0 :         psInfo->iCurItem = 0;
     651               0 :         if (psInfo->nPrecision == AVC_DOUBLE_PREC)
     652               0 :             psInfo->numItems = 2;
     653                 :         else
     654               0 :             psInfo->numItems = 1;
     655                 : 
     656                 :         /* And return the LAB header line.
     657                 :          */
     658               0 :         sprintf(psInfo->pszBuf, "%10d%10d", psLab->nValue, psLab->nPolyId);
     659                 : 
     660               0 :         AVCPrintRealValue(psInfo->pszBuf, psInfo->nPrecision, AVCFileLAB,
     661                 :                         psLab->sCoord1.x);
     662               0 :         AVCPrintRealValue(psInfo->pszBuf, psInfo->nPrecision, AVCFileLAB,
     663                 :                         psLab->sCoord1.y);
     664                 : 
     665                 :     }
     666               0 :     else if (psInfo->iCurItem < psInfo->numItems)
     667                 :     {
     668                 :         /* Return next Label coordinates... 
     669                 :          */
     670               0 :         if (psInfo->nPrecision != AVC_DOUBLE_PREC)
     671                 :         {
     672                 :             /* Single precision, all on the same line
     673                 :              */
     674               0 :             psInfo->pszBuf[0] = '\0';
     675               0 :             AVCPrintRealValue(psInfo->pszBuf, psInfo->nPrecision, AVCFileLAB,
     676                 :                             psLab->sCoord2.x);
     677               0 :             AVCPrintRealValue(psInfo->pszBuf, psInfo->nPrecision, AVCFileLAB,
     678                 :                             psLab->sCoord2.y);
     679               0 :             AVCPrintRealValue(psInfo->pszBuf, psInfo->nPrecision, AVCFileLAB,
     680                 :                             psLab->sCoord3.x);
     681               0 :             AVCPrintRealValue(psInfo->pszBuf, psInfo->nPrecision, AVCFileLAB,
     682                 :                             psLab->sCoord3.y);
     683                 : 
     684                 :         }
     685               0 :         else if (psInfo->iCurItem == 0)
     686                 :         {
     687                 :             /* 2nd line, in a double precision coverage
     688                 :              */
     689               0 :             psInfo->pszBuf[0] = '\0';
     690               0 :             AVCPrintRealValue(psInfo->pszBuf, psInfo->nPrecision, AVCFileLAB,
     691                 :                             psLab->sCoord2.x);
     692               0 :             AVCPrintRealValue(psInfo->pszBuf, psInfo->nPrecision, AVCFileLAB,
     693                 :                             psLab->sCoord2.y);
     694                 :         }
     695                 :         else
     696                 :         {
     697                 :             /* 3rd line, in a double precision coverage
     698                 :              */
     699               0 :             psInfo->pszBuf[0] = '\0';
     700               0 :             AVCPrintRealValue(psInfo->pszBuf, psInfo->nPrecision, AVCFileLAB,
     701                 :                             psLab->sCoord3.x);
     702               0 :             AVCPrintRealValue(psInfo->pszBuf, psInfo->nPrecision, AVCFileLAB,
     703                 :                             psLab->sCoord3.y);
     704                 :         }
     705                 : 
     706               0 :         psInfo->iCurItem++;
     707                 :     }
     708                 :     else
     709                 :     {
     710                 :         /* No more lines to generate for this LAB.
     711                 :          */
     712               0 :         return NULL;
     713                 :     }
     714                 : 
     715               0 :     return psInfo->pszBuf;
     716                 : }
     717                 : 
     718                 : /*=====================================================================
     719                 :                             TOL stuff
     720                 :  =====================================================================*/
     721                 : 
     722                 : /**********************************************************************
     723                 :  *                          AVCE00GenTol()
     724                 :  *
     725                 :  * Generate the next line of an E00 TOL (Tolerance) entry.
     726                 :  *
     727                 :  * This function should be called once with bCont=FALSE to get the
     728                 :  * first E00 line for the current TOL, and then call with bCont=TRUE
     729                 :  * to get all the other lines for this TOL.
     730                 :  *
     731                 :  * The function returns NULL when there are no more lines to generate
     732                 :  * for this TOL entry.
     733                 :  **********************************************************************/
     734                 : const char *AVCE00GenTol(AVCE00GenInfo *psInfo, AVCTol *psTol, GBool bCont)
     735               0 : {
     736               0 :     if (bCont == TRUE)
     737                 :     {
     738                 :         /*--------------------------------------------------------- 
     739                 :          * TOL entries are only 1 line, we support the bCont flag
     740                 :          * only for compatibility with the other AVCE00Gen*() functions.
     741                 :          *--------------------------------------------------------*/
     742               0 :         return NULL;
     743                 :     }
     744                 : 
     745               0 :     sprintf(psInfo->pszBuf, "%10d%10d", psTol->nIndex, psTol->nFlag);
     746               0 :     AVCPrintRealValue(psInfo->pszBuf, psInfo->nPrecision, AVCFileTOL,
     747                 :                     psTol->dValue);
     748                 : 
     749               0 :     return psInfo->pszBuf;
     750                 : }
     751                 : 
     752                 : /*=====================================================================
     753                 :                             PRJ stuff
     754                 :  =====================================================================*/
     755                 : 
     756                 : /**********************************************************************
     757                 :  *                          AVCE00GenPrj()
     758                 :  *
     759                 :  * Generate the next line of an E00 PRJ (Projection) section.
     760                 :  *
     761                 :  * This function should be called once with bCont=FALSE to get the
     762                 :  * first E00 line for the current PRJ, and then call with bCont=TRUE
     763                 :  * to get all the other lines for this PRJ.
     764                 :  *
     765                 :  * The function returns NULL when there are no more lines to generate
     766                 :  * for this PRJ entry.
     767                 :  **********************************************************************/
     768                 : const char *AVCE00GenPrj(AVCE00GenInfo *psInfo, char **papszPrj, GBool bCont)
     769               0 : {
     770               0 :     if (bCont == FALSE)
     771                 :     {
     772                 :         /*--------------------------------------------------------- 
     773                 :          * Initialize the psInfo structure with info about the
     774                 :          * current PRJ. (numItems = Number of lines to output)
     775                 :          *--------------------------------------------------------*/
     776               0 :         psInfo->iCurItem = 0;
     777               0 :         psInfo->numItems = CSLCount(papszPrj) * 2;
     778                 :     }
     779                 : 
     780               0 :     if (psInfo->iCurItem < psInfo->numItems)
     781                 :     {
     782                 :         /*--------------------------------------------------------- 
     783                 :          * Return the next PRJ section line.  Note that every
     784                 :          * second line of the output is only a "~".
     785                 :          *--------------------------------------------------------*/
     786                 : 
     787               0 :         if (psInfo->iCurItem % 2 == 0)
     788                 :         {
     789                 :             /*-----------------------------------------------------
     790                 :              * In theory we should split lines longer than 80 chars on
     791                 :              * several lines, but I won't do it for now since I never
     792                 :              * saw any projection line longer than 80 chars.
     793                 :              *----------------------------------------------------*/
     794               0 :             sprintf(psInfo->pszBuf, "%s", papszPrj[psInfo->iCurItem/2]);
     795                 :         }
     796                 :         else
     797                 :         {
     798                 :             /*-----------------------------------------------------
     799                 :              * Every second line in a PRJ section contains only a "~",
     800                 :              * this is a way to tell that the previous line was complete.
     801                 :              *----------------------------------------------------*/
     802               0 :             sprintf(psInfo->pszBuf, "~");
     803                 :         }
     804                 : 
     805               0 :         psInfo->iCurItem++;
     806                 :     }
     807                 :     else
     808                 :     {
     809                 :         /* No more lines to generate for this PRJ.
     810                 :          */
     811               0 :         return NULL;
     812                 :     }
     813                 : 
     814               0 :     return psInfo->pszBuf;
     815                 : }
     816                 : 
     817                 : 
     818                 : /*=====================================================================
     819                 :                             TXT stuff
     820                 :  =====================================================================*/
     821                 : 
     822                 : /**********************************************************************
     823                 :  *                          AVCE00GenTxt()
     824                 :  *
     825                 :  * Generate the next line of an E00 TXT (Annotation) entry.
     826                 :  *
     827                 :  * This function should be called once with bCont=FALSE to get the
     828                 :  * first E00 line for the current TXT, and then call with bCont=TRUE
     829                 :  * to get all the other lines for this TXT.
     830                 :  *
     831                 :  * The function returns NULL when there are no more lines to generate
     832                 :  * for this TXT entry.
     833                 :  **********************************************************************/
     834                 : const char *AVCE00GenTxt(AVCE00GenInfo *psInfo, AVCTxt *psTxt, GBool bCont)
     835               0 : {
     836                 :     int numFixedLines;
     837                 : 
     838                 :     /* numFixedLines is the number of lines to generate before the line(s)
     839                 :      * with the text string 
     840                 :      */
     841               0 :     if (psInfo->nPrecision == AVC_SINGLE_PREC)
     842               0 :         numFixedLines = 4;
     843                 :     else
     844               0 :         numFixedLines = 6;
     845                 : 
     846               0 :     if (bCont == FALSE)
     847                 :     {
     848                 :         /*-------------------------------------------------------------
     849                 :          * Initialize the psInfo structure with info about the
     850                 :          * current TXT. (numItems = Number of lines excluding header)
     851                 :          *------------------------------------------------------------*/
     852               0 :         psInfo->iCurItem = 0;
     853               0 :         psInfo->numItems = numFixedLines + ((psTxt->numChars-1)/80 + 1);
     854                 : 
     855                 :         /* And return the TXT header line.
     856                 :          */
     857               0 :         sprintf(psInfo->pszBuf, "%10d%10d%10d%10d%10d", 
     858                 :                 psTxt->nLevel, psTxt->numVerticesLine - 1, 
     859                 :                 psTxt->numVerticesArrow, psTxt->nSymbol, psTxt->numChars);
     860                 :     }
     861               0 :     else if (psInfo->iCurItem < psInfo->numItems &&
     862                 :              psInfo->iCurItem < numFixedLines-1)
     863                 :     {
     864                 :         /*-------------------------------------------------------------
     865                 :          * Return next line of coordinates... start by placing the coord. 
     866                 :          * values in the order that they should appear, and then generate the 
     867                 :          * current line
     868                 :          * (This is a little bit less efficient, but will give much easier
     869                 :          *  code to read ;-)
     870                 :          *------------------------------------------------------------*/
     871                 :         double  dXY[15];
     872                 :         int     i, nFirstValue, numValuesPerLine;
     873               0 :         for(i=0; i<14; i++)
     874               0 :             dXY[i] = 0.0;
     875                 : 
     876               0 :         dXY[14] = psTxt->dHeight;
     877                 : 
     878                 :         /* note that the first vertex in the vertices list is never exported
     879                 :          */
     880               0 :         for(i=0; i < 4 && i< (psTxt->numVerticesLine-1); i++)
     881                 :         {
     882               0 :             dXY[i] = psTxt->pasVertices[i+1].x;
     883               0 :             dXY[i+4] = psTxt->pasVertices[i+1].y;
     884                 :         }
     885               0 :         for(i=0; i < 3 && i<ABS(psTxt->numVerticesArrow); i++)
     886                 :         {
     887               0 :             dXY[i+8] = psTxt->pasVertices[i+psTxt->numVerticesLine].x;
     888               0 :             dXY[i+11] = psTxt->pasVertices[i+psTxt->numVerticesLine].y;
     889                 :         }
     890                 : 
     891                 :         /* OK, now that we prepared the coord. values, return the next line
     892                 :          * of coordinates.  The only difference between double and single
     893                 :          * precision is the number of coordinates per line.
     894                 :          */
     895               0 :         if (psInfo->nPrecision != AVC_DOUBLE_PREC)
     896                 :         {
     897                 :             /* Single precision
     898                 :              */
     899               0 :             numValuesPerLine = 5;
     900                 :         }
     901                 :         else
     902                 :         {
     903                 :             /* Double precision
     904                 :              */
     905               0 :             numValuesPerLine = 3;
     906                 :         }       
     907                 :      
     908               0 :         nFirstValue = psInfo->iCurItem*numValuesPerLine; 
     909               0 :         psInfo->pszBuf[0] = '\0';
     910               0 :         for(i=0; i<numValuesPerLine; i++)
     911                 :         {
     912               0 :             AVCPrintRealValue(psInfo->pszBuf, psInfo->nPrecision, AVCFileTXT,
     913                 :                             dXY[nFirstValue+i] );
     914                 :         }
     915                 : 
     916               0 :         psInfo->iCurItem++;
     917                 :     }
     918               0 :     else if (psInfo->iCurItem < psInfo->numItems &&
     919                 :              psInfo->iCurItem == numFixedLines-1)
     920                 :     {
     921                 :         /*-------------------------------------------------------------
     922                 :          * Line with a -1.000E+02 value, ALWAYS SINGLE PRECISION !!!
     923                 :          *------------------------------------------------------------*/
     924               0 :         psInfo->pszBuf[0] = '\0';
     925               0 :         AVCPrintRealValue(psInfo->pszBuf, AVC_SINGLE_PREC, AVCFileTXT,
     926                 :                         psTxt->f_1e2 );
     927               0 :         psInfo->iCurItem++;
     928                 :     }
     929               0 :     else if (psInfo->iCurItem < psInfo->numItems &&
     930                 :              psInfo->iCurItem >= numFixedLines )
     931                 :     {
     932                 :         /*-------------------------------------------------------------
     933                 :          * Last line, contains the text string
     934                 :          * Strings longer than 80 chars have to be in 80 chars chunks
     935                 :          *------------------------------------------------------------*/
     936                 :         int numLines, iLine;
     937               0 :         numLines = (psTxt->numChars-1)/80 + 1;
     938               0 :         iLine = numLines - (psInfo->numItems - psInfo->iCurItem);
     939                 : 
     940               0 :         if ((int)strlen((char*)psTxt->pszText) > (iLine*80))
     941               0 :             sprintf(psInfo->pszBuf, "%-.80s", psTxt->pszText + (iLine*80) );
     942                 :         else 
     943               0 :             psInfo->pszBuf[0] = '\0';
     944                 : 
     945               0 :         psInfo->iCurItem++;
     946                 :     }
     947                 :     else
     948                 :     {
     949                 :         /* No more lines to generate for this TXT.
     950                 :          */
     951               0 :         return NULL;
     952                 :     }
     953                 : 
     954               0 :     return psInfo->pszBuf;
     955                 : }
     956                 : 
     957                 : /*=====================================================================
     958                 :                             TX6 stuff
     959                 :  =====================================================================*/
     960                 : 
     961                 : /**********************************************************************
     962                 :  *                          AVCE00GenTx6()
     963                 :  *
     964                 :  * Generate the next line of an E00 TX6 (Annotation) entry.
     965                 :  *
     966                 :  * This function should be called once with bCont=FALSE to get the
     967                 :  * first E00 line for the current TX6, and then call with bCont=TRUE
     968                 :  * to get all the other lines for this TX6.
     969                 :  *
     970                 :  * Note that E00 files can also contain TX7 sections, they seem identical
     971                 :  * to TX6 sections, except for one value in each entry, and it was
     972                 :  * impossible to find where this value comes from... so we will always
     973                 :  * generate TX6 sections and not bother with TX7.
     974                 :  *
     975                 :  * The function returns NULL when there are no more lines to generate
     976                 :  * for this TX6 entry.
     977                 :  **********************************************************************/
     978                 : const char *AVCE00GenTx6(AVCE00GenInfo *psInfo, AVCTxt *psTxt, GBool bCont)
     979               0 : {
     980               0 :     if (bCont == FALSE)
     981                 :     {
     982                 :         /*-------------------------------------------------------------
     983                 :          * Initialize the psInfo structure with info about the
     984                 :          * current TX6. (numItems = Number of lines excluding header)
     985                 :          *------------------------------------------------------------*/
     986               0 :         psInfo->iCurItem = 0;
     987               0 :         psInfo->numItems = 8 + psTxt->numVerticesLine + 
     988                 :                                ABS(psTxt->numVerticesArrow) + 
     989                 :                                          ((psTxt->numChars-1)/80 + 1);
     990                 : 
     991                 :         /* And return the TX6 header line.
     992                 :          */
     993               0 :         sprintf(psInfo->pszBuf, "%10d%10d%10d%10d%10d%10d%10d", 
     994                 :                 psTxt->nUserId, psTxt->nLevel, psTxt->numVerticesLine, 
     995                 :                 psTxt->numVerticesArrow, psTxt->nSymbol, psTxt->n28,
     996                 :                 psTxt->numChars);
     997                 :     }
     998               0 :     else if (psInfo->iCurItem < psInfo->numItems && 
     999                 :              psInfo->iCurItem < 6)
    1000                 :     {
    1001                 :         /*-------------------------------------------------------------
    1002                 :          * Text Justification stuff... 2 sets of 20 int16 values.
    1003                 :          *------------------------------------------------------------*/
    1004                 :         GInt16  *pValue;
    1005                 : 
    1006               0 :         if (psInfo->iCurItem < 3)
    1007               0 :             pValue = psTxt->anJust2 + psInfo->iCurItem * 7;
    1008                 :         else
    1009               0 :             pValue = psTxt->anJust1 + (psInfo->iCurItem-3) * 7;
    1010                 : 
    1011               0 :         if (psInfo->iCurItem == 2 || psInfo->iCurItem == 5)
    1012                 :         {
    1013               0 :             sprintf(psInfo->pszBuf, "%10d%10d%10d%10d%10d%10d",
    1014                 :                                 pValue[0], pValue[1], pValue[2], 
    1015                 :                                 pValue[3], pValue[4], pValue[5]);
    1016                 :         }
    1017                 :         else
    1018                 :         {
    1019               0 :             sprintf(psInfo->pszBuf, "%10d%10d%10d%10d%10d%10d%10d",
    1020                 :                                 pValue[0], pValue[1], pValue[2], 
    1021                 :                                 pValue[3], pValue[4], pValue[5], pValue[6]);
    1022                 :         }
    1023                 : 
    1024               0 :         psInfo->iCurItem++;
    1025                 :     }
    1026               0 :     else if (psInfo->iCurItem < psInfo->numItems && 
    1027                 :              psInfo->iCurItem == 6)
    1028                 :     {
    1029                 :         /*-------------------------------------------------------------
    1030                 :          * Line with a -1.000E+02 value, ALWAYS SINGLE PRECISION !!!
    1031                 :          *------------------------------------------------------------*/
    1032               0 :         psInfo->pszBuf[0] = '\0';
    1033               0 :         AVCPrintRealValue(psInfo->pszBuf, AVC_SINGLE_PREC, AVCFileTX6,
    1034                 :                         psTxt->f_1e2 );
    1035               0 :         psInfo->iCurItem++;
    1036                 :     }
    1037               0 :     else if (psInfo->iCurItem < psInfo->numItems && 
    1038                 :              psInfo->iCurItem == 7)
    1039                 :     {
    1040                 :         /*-------------------------------------------------------------
    1041                 :          * Line with 3 values, 1st value is probably text height.
    1042                 :          *------------------------------------------------------------*/
    1043               0 :         psInfo->pszBuf[0] = '\0';
    1044               0 :         AVCPrintRealValue(psInfo->pszBuf, psInfo->nPrecision, AVCFileTX6,
    1045                 :                         psTxt->dHeight );
    1046               0 :         AVCPrintRealValue(psInfo->pszBuf, psInfo->nPrecision, AVCFileTX6,
    1047                 :                         psTxt->dV2 );
    1048               0 :         AVCPrintRealValue(psInfo->pszBuf, psInfo->nPrecision, AVCFileTX6,
    1049                 :                         psTxt->dV3 );
    1050               0 :         psInfo->iCurItem++;
    1051                 :     }
    1052               0 :     else if (psInfo->iCurItem < psInfo->numItems-((psTxt->numChars-1)/80 + 1))
    1053                 :     {
    1054                 :         /*-------------------------------------------------------------
    1055                 :          * One line for each pair of X,Y coordinates
    1056                 :          *------------------------------------------------------------*/
    1057               0 :         psInfo->pszBuf[0] = '\0';
    1058                 : 
    1059               0 :         AVCPrintRealValue(psInfo->pszBuf, psInfo->nPrecision, AVCFileTX6,
    1060                 :                         psTxt->pasVertices[ psInfo->iCurItem-8 ].x );
    1061               0 :         AVCPrintRealValue(psInfo->pszBuf, psInfo->nPrecision, AVCFileTX6,
    1062                 :                         psTxt->pasVertices[ psInfo->iCurItem-8 ].y );
    1063                 : 
    1064               0 :         psInfo->iCurItem++;
    1065                 :     }
    1066               0 :     else if (psInfo->iCurItem < psInfo->numItems &&
    1067                 :              psInfo->iCurItem >= psInfo->numItems-((psTxt->numChars-1)/80 + 1))
    1068                 :     {
    1069                 :         /*-------------------------------------------------------------
    1070                 :          * Last line, contains the text string
    1071                 :          * Strings longer than 80 chars have to be in 80 chars chunks
    1072                 :          *------------------------------------------------------------*/
    1073                 :         int numLines, iLine;
    1074               0 :         numLines = (psTxt->numChars-1)/80 + 1;
    1075               0 :         iLine = numLines - (psInfo->numItems - psInfo->iCurItem);
    1076                 : 
    1077               0 :         if ((int)strlen((char*)psTxt->pszText) > (iLine*80))
    1078               0 :             sprintf(psInfo->pszBuf, "%-.80s", psTxt->pszText + (iLine*80) );
    1079                 :         else 
    1080               0 :             psInfo->pszBuf[0] = '\0';
    1081                 : 
    1082               0 :         psInfo->iCurItem++;
    1083                 :     }
    1084                 :     else
    1085                 :     {
    1086                 :         /* No more lines to generate for this TX6.
    1087                 :          */
    1088               0 :         return NULL;
    1089                 :     }
    1090                 : 
    1091               0 :     return psInfo->pszBuf;
    1092                 : }
    1093                 : 
    1094                 : 
    1095                 : /*=====================================================================
    1096                 :                             RXP stuff
    1097                 :  =====================================================================*/
    1098                 : 
    1099                 : /**********************************************************************
    1100                 :  *                          AVCE00GenRxp()
    1101                 :  *
    1102                 :  * Generate the next line of an E00 RXP entry (RXPs are related to regions).
    1103                 :  *
    1104                 :  * This function should be called once with bCont=FALSE to get the
    1105                 :  * first E00 line for the current RXP, and then call with bCont=TRUE
    1106                 :  * to get all the other lines for this RXP.
    1107                 :  *
    1108                 :  * The function returns NULL when there are no more lines to generate
    1109                 :  * for this RXP entry.
    1110                 :  **********************************************************************/
    1111                 : const char *AVCE00GenRxp(AVCE00GenInfo *psInfo, AVCRxp *psRxp, GBool bCont)
    1112               0 : {
    1113               0 :     if (bCont == TRUE)
    1114                 :     {
    1115                 :         /*--------------------------------------------------------- 
    1116                 :          * RXP entries are only 1 line, we support the bCont flag
    1117                 :          * only for compatibility with the other AVCE00Gen*() functions.
    1118                 :          *--------------------------------------------------------*/
    1119               0 :         return NULL;
    1120                 :     }
    1121                 : 
    1122               0 :     sprintf(psInfo->pszBuf, "%10d%10d", psRxp->n1, psRxp->n2);
    1123                 : 
    1124               0 :     return psInfo->pszBuf;
    1125                 : }
    1126                 : 
    1127                 : 
    1128                 : 
    1129                 : /*=====================================================================
    1130                 :                             TABLE stuff
    1131                 :  =====================================================================*/
    1132                 : 
    1133                 : /**********************************************************************
    1134                 :  *                          AVCE00GenTableHdr()
    1135                 :  *
    1136                 :  * Generate the next line of an E00 Table header.
    1137                 :  *
    1138                 :  * This function should be called once with bCont=FALSE to get the
    1139                 :  * first E00 line for the current table header, and then call with 
    1140                 :  * bCont=TRUE to get all the other lines.
    1141                 :  *
    1142                 :  * The function returns NULL when there are no more lines to generate.
    1143                 :  **********************************************************************/
    1144                 : const char *AVCE00GenTableHdr(AVCE00GenInfo *psInfo, AVCTableDef *psDef,
    1145                 :                               GBool bCont)
    1146               0 : {
    1147               0 :     if (bCont == FALSE)
    1148                 :     {
    1149                 :         int nRecSize;
    1150                 :         /* Initialize the psInfo structure with info about the
    1151                 :          * current Table Header
    1152                 :          */
    1153               0 :         psInfo->iCurItem = 0;
    1154               0 :         psInfo->numItems = psDef->numFields;
    1155                 : 
    1156               0 :         nRecSize = psDef->nRecSize;
    1157                 : #ifdef AVC_MAP_TYPE40_TO_DOUBLE
    1158                 :         {
    1159                 :             /* Adjust Table record size if we're remapping type 40 fields */
    1160                 :             int i;
    1161                 :             for(i=0; i<psDef->numFields; i++)
    1162                 :             {
    1163                 :                 if (psDef->pasFieldDef[i].nType1*10 == AVC_FT_FIXNUM &&
    1164                 :                     psDef->pasFieldDef[i].nSize > 8)
    1165                 :                 {
    1166                 :                     nRecSize -= psDef->pasFieldDef[i].nSize;
    1167                 :                     nRecSize += 8;
    1168                 :                 }
    1169                 :             }
    1170                 :             nRecSize = ((nRecSize+1)/2)*2;
    1171                 :         }
    1172                 : #endif
    1173                 : 
    1174                 :         /* And return the header's header line(!).
    1175                 :          */
    1176               0 :         sprintf(psInfo->pszBuf, "%-32.32s%s%4d%4d%4d%10d", 
    1177                 :                                             psDef->szTableName,
    1178                 :                                             psDef->szExternal,
    1179                 :                                             psDef->numFields,
    1180                 :                                             psDef->numFields,
    1181                 :                                             nRecSize,
    1182                 :                                             psDef->numRecords);
    1183                 :     }
    1184               0 :     else if (psInfo->iCurItem < psInfo->numItems)
    1185                 :     {
    1186                 :         int nSize, nType, nOffset;
    1187                 : 
    1188               0 :         nSize = psDef->pasFieldDef[psInfo->iCurItem].nSize;
    1189               0 :         nType = psDef->pasFieldDef[psInfo->iCurItem].nType1 * 10;
    1190               0 :         nOffset = psDef->pasFieldDef[psInfo->iCurItem].nOffset;
    1191                 : 
    1192                 : #ifdef AVC_MAP_TYPE40_TO_DOUBLE
    1193                 :         /* Type 40 fields with more than 12 digits written to E00 by Arc/Info
    1194                 :          * will lose some digits of precision (and we starts losing them at 8 
    1195                 :          * with the way AVC lib writes type 40).  This (optional) hack will 
    1196                 :          * remap type 40 fields with more than 8 digits to double precision 
    1197                 :          * floats which can carry up to 18 digits of precision.  (bug 599)
    1198                 :          */
    1199                 :         if (nType == AVC_FT_FIXNUM && nSize > 8)
    1200                 :         {
    1201                 :             /* Remap to double-precision float */
    1202                 :             nType = AVC_FT_BINFLOAT;
    1203                 :             nSize = 8;
    1204                 :         }
    1205                 : 
    1206                 :         /* Adjust field offset if this field is preceded by any type40 fields
    1207                 :          * that were remapped. 
    1208                 :          */
    1209                 :         {
    1210                 :             int i;
    1211                 :             for(i=0; i < psInfo->iCurItem; i++)
    1212                 :             {
    1213                 :                 if (psDef->pasFieldDef[i].nType1*10 == AVC_FT_FIXNUM &&
    1214                 :                     psDef->pasFieldDef[i].nSize > 8)
    1215                 :                 {
    1216                 :                     nOffset -= psDef->pasFieldDef[i].nSize;
    1217                 :                     nOffset += 8;
    1218                 :                 }
    1219                 :             }
    1220                 :         }
    1221                 : #endif
    1222                 :         /* Return next Field definition line
    1223                 :          */
    1224               0 :         sprintf(psInfo->pszBuf,
    1225                 :                 "%-16.16s%3d%2d%4d%1d%2d%4d%2d%3d%2d%4d%4d%2d%-16.16s%4d-",
    1226                 :                 psDef->pasFieldDef[psInfo->iCurItem].szName,
    1227                 :                 nSize,
    1228                 :                 psDef->pasFieldDef[psInfo->iCurItem].v2,
    1229                 :                 nOffset,
    1230                 :                 psDef->pasFieldDef[psInfo->iCurItem].v4,
    1231                 :                 psDef->pasFieldDef[psInfo->iCurItem].v5,
    1232                 :                 psDef->pasFieldDef[psInfo->iCurItem].nFmtWidth,
    1233                 :                 psDef->pasFieldDef[psInfo->iCurItem].nFmtPrec,
    1234                 :                 nType,
    1235                 :                 psDef->pasFieldDef[psInfo->iCurItem].v10,
    1236                 :                 psDef->pasFieldDef[psInfo->iCurItem].v11,
    1237                 :                 psDef->pasFieldDef[psInfo->iCurItem].v12,
    1238                 :                 psDef->pasFieldDef[psInfo->iCurItem].v13,
    1239                 :                 psDef->pasFieldDef[psInfo->iCurItem].szAltName,
    1240                 :                 psDef->pasFieldDef[psInfo->iCurItem].nIndex );
    1241                 : 
    1242                 : 
    1243               0 :         psInfo->iCurItem++;
    1244                 :     }
    1245                 :     else
    1246                 :     {
    1247                 :         /* No more lines to generate.
    1248                 :          */
    1249               0 :         return NULL;
    1250                 :     }
    1251                 : 
    1252               0 :     return psInfo->pszBuf;
    1253                 : }
    1254                 : 
    1255                 : /**********************************************************************
    1256                 :  *                          AVCE00GenTableRec()
    1257                 :  *
    1258                 :  * Generate the next line of an E00 Table Data Record.
    1259                 :  *
    1260                 :  * This function should be called once with bCont=FALSE to get the
    1261                 :  * first E00 line for the current table record, and then call with 
    1262                 :  * bCont=TRUE to get all the other lines.
    1263                 :  *
    1264                 :  * The function returns NULL when there are no more lines to generate.
    1265                 :  **********************************************************************/
    1266                 : const char *AVCE00GenTableRec(AVCE00GenInfo *psInfo, int numFields,
    1267                 :                               AVCFieldInfo *pasDef, AVCField *pasFields,
    1268                 :                               GBool bCont)
    1269               0 : {
    1270                 :     int     i, nSize, nType, nLen;
    1271                 :     char    *pszBuf2;
    1272                 : 
    1273               0 :     if (bCont == FALSE)
    1274                 :     {
    1275                 :         /*------------------------------------------------------------- 
    1276                 :          * Initialize the psInfo structure to be ready to process this
    1277                 :          * new Table Record
    1278                 :          *------------------------------------------------------------*/
    1279               0 :         psInfo->iCurItem = 0;
    1280                 : #ifdef AVC_MAP_TYPE40_TO_DOUBLE
    1281                 :         psInfo->numItems = _AVCE00ComputeRecSize(numFields, pasDef, TRUE);
    1282                 : #else
    1283               0 :         psInfo->numItems = _AVCE00ComputeRecSize(numFields, pasDef, FALSE);
    1284                 : #endif
    1285                 : 
    1286                 :         /*------------------------------------------------------------- 
    1287                 :          * First, we need to make sure that the output buffer is big 
    1288                 :          * enough to hold the whole record, plus 81 chars to hold
    1289                 :          * the line that we'll return to the caller.
    1290                 :          *------------------------------------------------------------*/
    1291               0 :         nSize = psInfo->numItems + 1 + 81;
    1292                 : 
    1293               0 :         if (psInfo->nBufSize < nSize)
    1294                 :         {
    1295               0 :             psInfo->pszBuf = (char*)CPLRealloc(psInfo->pszBuf,
    1296                 :                                                nSize*sizeof(char));
    1297               0 :             psInfo->nBufSize = nSize;
    1298                 :         }
    1299                 : 
    1300                 :         /*------------------------------------------------------------- 
    1301                 :          * Generate the whole record now, and we'll return it to the
    1302                 :          * caller by chunks of 80 chars.
    1303                 :          * The first 80 chars of the buffer will be used to return 
    1304                 :          * one line at a time, and the rest of the buffer is used to
    1305                 :          * hold the whole record.
    1306                 :          *------------------------------------------------------------*/
    1307               0 :         pszBuf2 = psInfo->pszBuf+81;
    1308                 : 
    1309               0 :         for(i=0; i<numFields; i++)
    1310                 :         {
    1311               0 :             nType = pasDef[i].nType1*10;
    1312               0 :             nSize = pasDef[i].nSize;
    1313                 : 
    1314               0 :             if (nType ==  AVC_FT_DATE || nType == AVC_FT_CHAR ||
    1315                 :                 nType == AVC_FT_FIXINT )
    1316                 :             {
    1317               0 :                 memcpy(pszBuf2, pasFields[i].pszStr, nSize * sizeof(char));
    1318               0 :                 pszBuf2 += nSize;
    1319                 :             }
    1320                 : #ifdef AVC_MAP_TYPE40_TO_DOUBLE
    1321                 :             /* See explanation in AVCE00GenTableHdr() about this hack to remap
    1322                 :              * type 40 fields to double precision floats.
    1323                 :              */
    1324                 :             else if (nType == AVC_FT_FIXNUM && nSize > 8)
    1325                 :             {
    1326                 :                 pszBuf2[0] = '\0';
    1327                 :                 /* NOTE: The E00 representation for a binary float is
    1328                 :                  * defined by its binary size, not by the coverage's
    1329                 :                  * precision.
    1330                 :                  */
    1331                 :                 nLen = AVCPrintRealValue(pszBuf2, AVC_DOUBLE_PREC,
    1332                 :                                          AVCFileTABLE,
    1333                 :                                          atof((char*)pasFields[i].pszStr));
    1334                 :                 pszBuf2 += nLen;
    1335                 :             }
    1336                 : #endif
    1337               0 :             else if (nType == AVC_FT_FIXNUM)
    1338                 :             {
    1339                 :                 /* TYPE 40 attributes are stored with 1 byte per digit
    1340                 :                  * in binary format, and as single precision floats in
    1341                 :                  * E00 tables, even in double precision coverages.
    1342                 :                  */
    1343               0 :                 pszBuf2[0] = '\0';
    1344               0 :                 nLen = AVCPrintRealValue(pszBuf2, AVC_SINGLE_PREC, 
    1345                 :                                        AVCFileTABLE,
    1346                 :                                          atof((char*)pasFields[i].pszStr));
    1347               0 :                 pszBuf2 += nLen;
    1348                 :             }
    1349               0 :             else if (nType == AVC_FT_BININT && nSize == 4)
    1350                 :             {
    1351               0 :                 sprintf(pszBuf2, "%11d", pasFields[i].nInt32);
    1352               0 :                 pszBuf2 += 11;
    1353                 :             }
    1354               0 :             else if (nType == AVC_FT_BININT && nSize == 2)
    1355                 :             {
    1356               0 :                 sprintf(pszBuf2, "%6d", pasFields[i].nInt16);
    1357               0 :                 pszBuf2 += 6;
    1358                 :             }
    1359               0 :             else if (nType == AVC_FT_BINFLOAT && nSize == 4)
    1360                 :             {
    1361               0 :                 pszBuf2[0] = '\0';
    1362                 :                 /* NOTE: The E00 representation for a binary float is
    1363                 :                  * defined by its binary size, not by the coverage's
    1364                 :                  * precision.
    1365                 :                  */
    1366               0 :                 nLen = AVCPrintRealValue(pszBuf2, AVC_SINGLE_PREC, 
    1367                 :                                        AVCFileTABLE,
    1368                 :                                        pasFields[i].fFloat);
    1369               0 :                 pszBuf2 += nLen;
    1370                 :             }
    1371               0 :             else if (nType == AVC_FT_BINFLOAT && nSize == 8)
    1372                 :             {
    1373               0 :                 pszBuf2[0] = '\0';
    1374                 :                 /* NOTE: The E00 representation for a binary float is
    1375                 :                  * defined by its binary size, not by the coverage's
    1376                 :                  * precision.
    1377                 :                  */
    1378               0 :                 nLen = AVCPrintRealValue(pszBuf2, AVC_DOUBLE_PREC,
    1379                 :                                        AVCFileTABLE,
    1380                 :                                        pasFields[i].dDouble);
    1381               0 :                 pszBuf2 += nLen;
    1382                 :             }
    1383                 :             else
    1384                 :             {
    1385                 :                 /*-----------------------------------------------------
    1386                 :                  * Hummm... unsupported field type...
    1387                 :                  *----------------------------------------------------*/
    1388               0 :                 CPLError(CE_Failure, CPLE_NotSupported,
    1389                 :                          "Unsupported field type: (type=%d, size=%d)",
    1390                 :                          nType, nSize);
    1391               0 :                 return NULL;
    1392                 :             }
    1393                 :         }
    1394                 : 
    1395               0 :         *pszBuf2 = '\0';
    1396                 : 
    1397                 :   /* Make sure that we remove any embedded NUL characters from the
    1398                 :    * data line before returning it, otherwise we may be accidentally
    1399                 :    * truncating results.
    1400                 :    */
    1401               0 :   while ( --pszBuf2 >= psInfo->pszBuf+81 )
    1402                 :   {
    1403               0 :             if ( *pszBuf2 == '\0' )
    1404                 :             {
    1405               0 :                 *pszBuf2 = ' ';
    1406                 :             }
    1407                 :   }
    1408                 :     }
    1409                 : 
    1410               0 :     if (psInfo->iCurItem < psInfo->numItems)
    1411                 :     {
    1412                 :         /*------------------------------------------------------------- 
    1413                 :          * Return the next 80 chars chunk.
    1414                 :          * The first 80 chars of the buffer is used to return 
    1415                 :          * one line at a time, and the rest of the buffer (chars 81+)
    1416                 :          * is used to hold the whole record.
    1417                 :          *------------------------------------------------------------*/
    1418               0 :         nLen = psInfo->numItems - psInfo->iCurItem;
    1419                 : 
    1420               0 :         if (nLen > 80)
    1421               0 :             nLen = 80;
    1422                 : 
    1423               0 :         strncpy(psInfo->pszBuf, psInfo->pszBuf+(81+psInfo->iCurItem), nLen);
    1424               0 :         psInfo->pszBuf[nLen] = '\0';
    1425                 : 
    1426               0 :         psInfo->iCurItem += nLen;
    1427                 : 
    1428                 :         /*------------------------------------------------------------- 
    1429                 :          * Arc/Info removes spaces at the end of the lines... let's 
    1430                 :          * remove them as well since it can reduce the E00 file size.
    1431                 :          *------------------------------------------------------------*/
    1432               0 :         nLen--;
    1433               0 :         while(nLen >= 0 && psInfo->pszBuf[nLen] == ' ')
    1434                 :         {
    1435               0 :             psInfo->pszBuf[nLen] = '\0';
    1436               0 :             nLen--;
    1437                 :         }
    1438                 :     }
    1439                 :     else
    1440                 :     {
    1441                 :         /* No more lines to generate.
    1442                 :          */
    1443               0 :         return NULL;
    1444                 :     }
    1445                 : 
    1446               0 :     return psInfo->pszBuf;
    1447                 : }
    1448                 : 

Generated by: LTP GCOV extension version 1.5