/[thuban]/branches/WIP-pyshapelib-bramz/libraries/shapelib/dbfopen.c
ViewVC logotype

Annotation of /branches/WIP-pyshapelib-bramz/libraries/shapelib/dbfopen.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1612 - (hide annotations)
Tue Aug 19 21:29:25 2003 UTC (21 years, 6 months ago) by jan
Original Path: trunk/thuban/libraries/shapelib/dbfopen.c
File MIME type: text/plain
File size: 47197 byte(s)
These files have been moved here from thuban/extensions/shapelib/
See there in the Attic for the older history.

1 jan 1612 /******************************************************************************
2     * $Id$
3     *
4     * Project: Shapelib
5     * Purpose: Implementation of .dbf access API documented in dbf_api.html.
6     * Author: Frank Warmerdam, [email protected]
7     *
8     ******************************************************************************
9     * Copyright (c) 1999, Frank Warmerdam
10     *
11     * This software is available under the following "MIT Style" license,
12     * or at the option of the licensee under the LGPL (see LICENSE.LGPL). This
13     * option is discussed in more detail in shapelib.html.
14     *
15     * --
16     *
17     * Permission is hereby granted, free of charge, to any person obtaining a
18     * copy of this software and associated documentation files (the "Software"),
19     * to deal in the Software without restriction, including without limitation
20     * the rights to use, copy, modify, merge, publish, distribute, sublicense,
21     * and/or sell copies of the Software, and to permit persons to whom the
22     * Software is furnished to do so, subject to the following conditions:
23     *
24     * The above copyright notice and this permission notice shall be included
25     * in all copies or substantial portions of the Software.
26     *
27     * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
28     * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
29     * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
30     * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
31     * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
32     * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
33     * DEALINGS IN THE SOFTWARE.
34     ******************************************************************************
35     *
36     * $Log$
37     * Revision 1.1 2003/08/19 21:29:25 jan
38     * These files have been moved here from thuban/extensions/shapelib/
39     * See there in the Attic for the older history.
40     *
41     * Revision 1.4 2002/08/22 16:00:01 bh
42     * * extensions/shapelib/shapefil.h (DBFCommit),
43     * extensions/shapelib/dbfopen.c (DBFCommit): New API function to
44     * commit any changes made to the DBF file.
45     *
46     * Revision 1.3 2002/05/07 14:09:45 bh
47     * * extensions/shapelib/shpopen.c, extensions/shapelib/shapefil.h,
48     * extensions/shapelib/dbfopen.c: Really update to the versions of
49     * shapelib 1.2.9. For some reason it wasn't really done on
50     * 2002-04-11.
51     *
52     * Revision 1.37 2001/07/04 05:18:09 warmerda
53     * do last fix properly
54     *
55     * Revision 1.36 2001/07/04 05:16:09 warmerda
56     * fixed fieldname comparison in DBFGetFieldIndex
57     *
58     * Revision 1.35 2001/06/22 02:10:06 warmerda
59     * fixed NULL shape support with help from Jim Matthews
60     *
61     * Revision 1.33 2001/05/31 19:20:13 warmerda
62     * added DBFGetFieldIndex()
63     *
64     * Revision 1.32 2001/05/31 18:15:40 warmerda
65     * Added support for NULL fields in DBF files
66     *
67     * Revision 1.31 2001/05/23 13:36:52 warmerda
68     * added use of SHPAPI_CALL
69     *
70     * Revision 1.30 2000/12/05 14:43:38 warmerda
71     * DBReadAttribute() white space trimming bug fix
72     *
73     * Revision 1.29 2000/10/05 14:36:44 warmerda
74     * fix bug with writing very wide numeric fields
75     *
76     * Revision 1.28 2000/09/25 14:18:07 warmerda
77     * Added some casts of strlen() return result to fix warnings on some
78     * systems, as submitted by Daniel.
79     *
80     * Revision 1.27 2000/09/25 14:15:51 warmerda
81     * added DBFGetNativeFieldType()
82     *
83     * Revision 1.26 2000/07/07 13:39:45 warmerda
84     * removed unused variables, and added system include files
85     *
86     * Revision 1.25 2000/05/29 18:19:13 warmerda
87     * avoid use of uchar, and adding casting fix
88     *
89     * Revision 1.24 2000/05/23 13:38:27 warmerda
90     * Added error checks on return results of fread() and fseek().
91     *
92     * Revision 1.23 2000/05/23 13:25:49 warmerda
93     * Avoid crashing if field or record are out of range in dbfread*attribute().
94     *
95     * Revision 1.22 1999/12/15 13:47:24 warmerda
96     * Added stdlib.h to ensure that atof() is prototyped.
97     *
98     * Revision 1.21 1999/12/13 17:25:46 warmerda
99     * Added support for upper case .DBF extention.
100     *
101     * Revision 1.20 1999/11/30 16:32:11 warmerda
102     * Use atof() instead of sscanf().
103     *
104     * Revision 1.19 1999/11/05 14:12:04 warmerda
105     * updated license terms
106     *
107     * Revision 1.18 1999/07/27 00:53:28 warmerda
108     * ensure that whole old field value clear on write of string
109     *
110     * Revision 1.1 1999/07/05 18:58:07 warmerda
111     * New
112     *
113     * Revision 1.17 1999/06/11 19:14:12 warmerda
114     * Fixed some memory leaks.
115     *
116     * Revision 1.16 1999/06/11 19:04:11 warmerda
117     * Remoted some unused variables.
118     *
119     * Revision 1.15 1999/05/11 03:19:28 warmerda
120     * added new Tuple api, and improved extension handling - add from candrsn
121     *
122     * Revision 1.14 1999/05/04 15:01:48 warmerda
123     * Added 'F' support.
124     *
125     * Revision 1.13 1999/03/23 17:38:59 warmerda
126     * DBFAddField() now actually does return the new field number, or -1 if
127     * it fails.
128     *
129     * Revision 1.12 1999/03/06 02:54:46 warmerda
130     * Added logic to convert shapefile name to dbf filename in DBFOpen()
131     * for convenience.
132     *
133     * Revision 1.11 1998/12/31 15:30:34 warmerda
134     * Improved the interchangability of numeric and string attributes. Add
135     * white space trimming option for attributes.
136     *
137     * Revision 1.10 1998/12/03 16:36:44 warmerda
138     * Use r+b instead of rb+ for binary access.
139     *
140     * Revision 1.9 1998/12/03 15:34:23 warmerda
141     * Updated copyright message.
142     *
143     * Revision 1.8 1997/12/04 15:40:15 warmerda
144     * Added newline character after field definitions.
145     *
146     * Revision 1.7 1997/03/06 14:02:10 warmerda
147     * Ensure bUpdated is initialized.
148     *
149     * Revision 1.6 1996/02/12 04:54:41 warmerda
150     * Ensure that DBFWriteAttribute() returns TRUE if it succeeds.
151     *
152     * Revision 1.5 1995/10/21 03:15:12 warmerda
153     * Changed to use binary file access, and ensure that the
154     * field name field is zero filled, and limited to 10 chars.
155     *
156     * Revision 1.4 1995/08/24 18:10:42 warmerda
157     * Added use of SfRealloc() to avoid pre-ANSI realloc() functions such
158     * as on the Sun.
159     *
160     * Revision 1.3 1995/08/04 03:15:16 warmerda
161     * Fixed up header.
162     *
163     * Revision 1.2 1995/08/04 03:14:43 warmerda
164     * Added header.
165     */
166    
167     static char rcsid[] =
168     "$Id$";
169    
170     #include "shapefil.h"
171    
172     #include <math.h>
173     #include <stdlib.h>
174     #include <ctype.h>
175     #include <string.h>
176    
177     #ifndef FALSE
178     # define FALSE 0
179     # define TRUE 1
180     #endif
181    
182     static int nStringFieldLen = 0;
183     static char * pszStringField = NULL;
184    
185     /************************************************************************/
186     /* SfRealloc() */
187     /* */
188     /* A realloc cover function that will access a NULL pointer as */
189     /* a valid input. */
190     /************************************************************************/
191    
192     static void * SfRealloc( void * pMem, int nNewSize )
193    
194     {
195     if( pMem == NULL )
196     return( (void *) malloc(nNewSize) );
197     else
198     return( (void *) realloc(pMem,nNewSize) );
199     }
200    
201     /************************************************************************/
202     /* DBFWriteHeader() */
203     /* */
204     /* This is called to write out the file header, and field */
205     /* descriptions before writing any actual data records. This */
206     /* also computes all the DBFDataSet field offset/size/decimals */
207     /* and so forth values. */
208     /************************************************************************/
209    
210     static void DBFWriteHeader(DBFHandle psDBF)
211    
212     {
213     unsigned char abyHeader[XBASE_FLDHDR_SZ];
214     int i;
215    
216     if( !psDBF->bNoHeader )
217     return;
218    
219     psDBF->bNoHeader = FALSE;
220    
221     /* -------------------------------------------------------------------- */
222     /* Initialize the file header information. */
223     /* -------------------------------------------------------------------- */
224     for( i = 0; i < XBASE_FLDHDR_SZ; i++ )
225     abyHeader[i] = 0;
226    
227     abyHeader[0] = 0x03; /* memo field? - just copying */
228    
229     /* date updated on close, record count preset at zero */
230    
231     abyHeader[8] = psDBF->nHeaderLength % 256;
232     abyHeader[9] = psDBF->nHeaderLength / 256;
233    
234     abyHeader[10] = psDBF->nRecordLength % 256;
235     abyHeader[11] = psDBF->nRecordLength / 256;
236    
237     /* -------------------------------------------------------------------- */
238     /* Write the initial 32 byte file header, and all the field */
239     /* descriptions. */
240     /* -------------------------------------------------------------------- */
241     fseek( psDBF->fp, 0, 0 );
242     fwrite( abyHeader, XBASE_FLDHDR_SZ, 1, psDBF->fp );
243     fwrite( psDBF->pszHeader, XBASE_FLDHDR_SZ, psDBF->nFields, psDBF->fp );
244    
245     /* -------------------------------------------------------------------- */
246     /* Write out the newline character if there is room for it. */
247     /* -------------------------------------------------------------------- */
248     if( psDBF->nHeaderLength > 32*psDBF->nFields + 32 )
249     {
250     char cNewline;
251    
252     cNewline = 0x0d;
253     fwrite( &cNewline, 1, 1, psDBF->fp );
254     }
255     }
256    
257     /************************************************************************/
258     /* DBFFlushRecord() */
259     /* */
260     /* Write out the current record if there is one. */
261     /************************************************************************/
262    
263     static void DBFFlushRecord( DBFHandle psDBF )
264    
265     {
266     int nRecordOffset;
267    
268     if( psDBF->bCurrentRecordModified && psDBF->nCurrentRecord > -1 )
269     {
270     psDBF->bCurrentRecordModified = FALSE;
271    
272     nRecordOffset = psDBF->nRecordLength * psDBF->nCurrentRecord
273     + psDBF->nHeaderLength;
274    
275     fseek( psDBF->fp, nRecordOffset, 0 );
276     fwrite( psDBF->pszCurrentRecord, psDBF->nRecordLength, 1, psDBF->fp );
277     }
278     }
279    
280     /************************************************************************/
281     /* DBFOpen() */
282     /* */
283     /* Open a .dbf file. */
284     /************************************************************************/
285    
286     DBFHandle SHPAPI_CALL
287     DBFOpen( const char * pszFilename, const char * pszAccess )
288    
289     {
290     DBFHandle psDBF;
291     unsigned char *pabyBuf;
292     int nFields, nRecords, nHeadLen, nRecLen, iField, i;
293     char *pszBasename, *pszFullname;
294    
295     /* -------------------------------------------------------------------- */
296     /* We only allow the access strings "rb" and "r+". */
297     /* -------------------------------------------------------------------- */
298     if( strcmp(pszAccess,"r") != 0 && strcmp(pszAccess,"r+") != 0
299     && strcmp(pszAccess,"rb") != 0 && strcmp(pszAccess,"rb+") != 0
300     && strcmp(pszAccess,"r+b") != 0 )
301     return( NULL );
302    
303     if( strcmp(pszAccess,"r") == 0 )
304     pszAccess = "rb";
305    
306     if( strcmp(pszAccess,"r+") == 0 )
307     pszAccess = "rb+";
308    
309     /* -------------------------------------------------------------------- */
310     /* Compute the base (layer) name. If there is any extension */
311     /* on the passed in filename we will strip it off. */
312     /* -------------------------------------------------------------------- */
313     pszBasename = (char *) malloc(strlen(pszFilename)+5);
314     strcpy( pszBasename, pszFilename );
315     for( i = strlen(pszBasename)-1;
316     i > 0 && pszBasename[i] != '.' && pszBasename[i] != '/'
317     && pszBasename[i] != '\\';
318     i-- ) {}
319    
320     if( pszBasename[i] == '.' )
321     pszBasename[i] = '\0';
322    
323     pszFullname = (char *) malloc(strlen(pszBasename) + 5);
324     sprintf( pszFullname, "%s.dbf", pszBasename );
325    
326     psDBF = (DBFHandle) calloc( 1, sizeof(DBFInfo) );
327     psDBF->fp = fopen( pszFullname, pszAccess );
328    
329     if( psDBF->fp == NULL )
330     {
331     sprintf( pszFullname, "%s.DBF", pszBasename );
332     psDBF->fp = fopen(pszFullname, pszAccess );
333     }
334    
335     free( pszBasename );
336     free( pszFullname );
337    
338     if( psDBF->fp == NULL )
339     {
340     free( psDBF );
341     return( NULL );
342     }
343    
344     psDBF->bNoHeader = FALSE;
345     psDBF->nCurrentRecord = -1;
346     psDBF->bCurrentRecordModified = FALSE;
347    
348     /* -------------------------------------------------------------------- */
349     /* Read Table Header info */
350     /* -------------------------------------------------------------------- */
351     pabyBuf = (unsigned char *) malloc(500);
352     fread( pabyBuf, 32, 1, psDBF->fp );
353    
354     psDBF->nRecords = nRecords =
355     pabyBuf[4] + pabyBuf[5]*256 + pabyBuf[6]*256*256 + pabyBuf[7]*256*256*256;
356    
357     psDBF->nHeaderLength = nHeadLen = pabyBuf[8] + pabyBuf[9]*256;
358     psDBF->nRecordLength = nRecLen = pabyBuf[10] + pabyBuf[11]*256;
359    
360     psDBF->nFields = nFields = (nHeadLen - 32) / 32;
361    
362     psDBF->pszCurrentRecord = (char *) malloc(nRecLen);
363    
364     /* -------------------------------------------------------------------- */
365     /* Read in Field Definitions */
366     /* -------------------------------------------------------------------- */
367    
368     pabyBuf = (unsigned char *) SfRealloc(pabyBuf,nHeadLen);
369     psDBF->pszHeader = (char *) pabyBuf;
370    
371     fseek( psDBF->fp, 32, 0 );
372     fread( pabyBuf, nHeadLen, 1, psDBF->fp );
373    
374     psDBF->panFieldOffset = (int *) malloc(sizeof(int) * nFields);
375     psDBF->panFieldSize = (int *) malloc(sizeof(int) * nFields);
376     psDBF->panFieldDecimals = (int *) malloc(sizeof(int) * nFields);
377     psDBF->pachFieldType = (char *) malloc(sizeof(char) * nFields);
378    
379     for( iField = 0; iField < nFields; iField++ )
380     {
381     unsigned char *pabyFInfo;
382    
383     pabyFInfo = pabyBuf+iField*32;
384    
385     if( pabyFInfo[11] == 'N' || pabyFInfo[11] == 'F' )
386     {
387     psDBF->panFieldSize[iField] = pabyFInfo[16];
388     psDBF->panFieldDecimals[iField] = pabyFInfo[17];
389     }
390     else
391     {
392     psDBF->panFieldSize[iField] = pabyFInfo[16] + pabyFInfo[17]*256;
393     psDBF->panFieldDecimals[iField] = 0;
394     }
395    
396     psDBF->pachFieldType[iField] = (char) pabyFInfo[11];
397     if( iField == 0 )
398     psDBF->panFieldOffset[iField] = 1;
399     else
400     psDBF->panFieldOffset[iField] =
401     psDBF->panFieldOffset[iField-1] + psDBF->panFieldSize[iField-1];
402     }
403    
404     return( psDBF );
405     }
406    
407     /************************************************************************/
408     /* DBFClose() */
409     /************************************************************************/
410    
411     void SHPAPI_CALL
412     DBFClose(DBFHandle psDBF)
413     {
414     /* -------------------------------------------------------------------- */
415     /* Write out header if not already written. */
416     /* -------------------------------------------------------------------- */
417     if( psDBF->bNoHeader )
418     DBFWriteHeader( psDBF );
419    
420     DBFFlushRecord( psDBF );
421    
422     /* -------------------------------------------------------------------- */
423     /* Update last access date, and number of records if we have */
424     /* write access. */
425     /* -------------------------------------------------------------------- */
426     if( psDBF->bUpdated )
427     {
428     unsigned char abyFileHeader[32];
429    
430     fseek( psDBF->fp, 0, 0 );
431     fread( abyFileHeader, 32, 1, psDBF->fp );
432    
433     abyFileHeader[1] = 95; /* YY */
434     abyFileHeader[2] = 7; /* MM */
435     abyFileHeader[3] = 26; /* DD */
436    
437     abyFileHeader[4] = psDBF->nRecords % 256;
438     abyFileHeader[5] = (psDBF->nRecords/256) % 256;
439     abyFileHeader[6] = (psDBF->nRecords/(256*256)) % 256;
440     abyFileHeader[7] = (psDBF->nRecords/(256*256*256)) % 256;
441    
442     fseek( psDBF->fp, 0, 0 );
443     fwrite( abyFileHeader, 32, 1, psDBF->fp );
444     }
445    
446     /* -------------------------------------------------------------------- */
447     /* Close, and free resources. */
448     /* -------------------------------------------------------------------- */
449     fclose( psDBF->fp );
450    
451     if( psDBF->panFieldOffset != NULL )
452     {
453     free( psDBF->panFieldOffset );
454     free( psDBF->panFieldSize );
455     free( psDBF->panFieldDecimals );
456     free( psDBF->pachFieldType );
457     }
458    
459     free( psDBF->pszHeader );
460     free( psDBF->pszCurrentRecord );
461    
462     free( psDBF );
463    
464     if( pszStringField != NULL )
465     {
466     free( pszStringField );
467     pszStringField = NULL;
468     nStringFieldLen = 0;
469     }
470     }
471    
472     /************************************************************************/
473     /* DBFCreate() */
474     /* */
475     /* Create a new .dbf file. */
476     /************************************************************************/
477    
478     DBFHandle SHPAPI_CALL
479     DBFCreate( const char * pszFilename )
480    
481     {
482     DBFHandle psDBF;
483     FILE *fp;
484     char *pszFullname, *pszBasename;
485     int i;
486    
487     /* -------------------------------------------------------------------- */
488     /* Compute the base (layer) name. If there is any extension */
489     /* on the passed in filename we will strip it off. */
490     /* -------------------------------------------------------------------- */
491     pszBasename = (char *) malloc(strlen(pszFilename)+5);
492     strcpy( pszBasename, pszFilename );
493     for( i = strlen(pszBasename)-1;
494     i > 0 && pszBasename[i] != '.' && pszBasename[i] != '/'
495     && pszBasename[i] != '\\';
496     i-- ) {}
497    
498     if( pszBasename[i] == '.' )
499     pszBasename[i] = '\0';
500    
501     pszFullname = (char *) malloc(strlen(pszBasename) + 5);
502     sprintf( pszFullname, "%s.dbf", pszBasename );
503     free( pszBasename );
504    
505     /* -------------------------------------------------------------------- */
506     /* Create the file. */
507     /* -------------------------------------------------------------------- */
508     fp = fopen( pszFullname, "wb" );
509     if( fp == NULL )
510     return( NULL );
511    
512     fputc( 0, fp );
513     fclose( fp );
514    
515     fp = fopen( pszFullname, "rb+" );
516     if( fp == NULL )
517     return( NULL );
518    
519     free( pszFullname );
520    
521     /* -------------------------------------------------------------------- */
522     /* Create the info structure. */
523     /* -------------------------------------------------------------------- */
524     psDBF = (DBFHandle) malloc(sizeof(DBFInfo));
525    
526     psDBF->fp = fp;
527     psDBF->nRecords = 0;
528     psDBF->nFields = 0;
529     psDBF->nRecordLength = 1;
530     psDBF->nHeaderLength = 33;
531    
532     psDBF->panFieldOffset = NULL;
533     psDBF->panFieldSize = NULL;
534     psDBF->panFieldDecimals = NULL;
535     psDBF->pachFieldType = NULL;
536     psDBF->pszHeader = NULL;
537    
538     psDBF->nCurrentRecord = -1;
539     psDBF->bCurrentRecordModified = FALSE;
540     psDBF->pszCurrentRecord = NULL;
541    
542     psDBF->bNoHeader = TRUE;
543    
544     return( psDBF );
545     }
546    
547     /************************************************************************/
548     /* DBFAddField() */
549     /* */
550     /* Add a field to a newly created .dbf file before any records */
551     /* are written. */
552     /************************************************************************/
553    
554     int SHPAPI_CALL
555     DBFAddField(DBFHandle psDBF, const char * pszFieldName,
556     DBFFieldType eType, int nWidth, int nDecimals )
557    
558     {
559     char *pszFInfo;
560     int i;
561    
562     /* -------------------------------------------------------------------- */
563     /* Do some checking to ensure we can add records to this file. */
564     /* -------------------------------------------------------------------- */
565     if( psDBF->nRecords > 0 )
566     return( -1 );
567    
568     if( !psDBF->bNoHeader )
569     return( -1 );
570    
571     if( eType != FTDouble && nDecimals != 0 )
572     return( -1 );
573    
574     /* -------------------------------------------------------------------- */
575     /* SfRealloc all the arrays larger to hold the additional field */
576     /* information. */
577     /* -------------------------------------------------------------------- */
578     psDBF->nFields++;
579    
580     psDBF->panFieldOffset = (int *)
581     SfRealloc( psDBF->panFieldOffset, sizeof(int) * psDBF->nFields );
582    
583     psDBF->panFieldSize = (int *)
584     SfRealloc( psDBF->panFieldSize, sizeof(int) * psDBF->nFields );
585    
586     psDBF->panFieldDecimals = (int *)
587     SfRealloc( psDBF->panFieldDecimals, sizeof(int) * psDBF->nFields );
588    
589     psDBF->pachFieldType = (char *)
590     SfRealloc( psDBF->pachFieldType, sizeof(char) * psDBF->nFields );
591    
592     /* -------------------------------------------------------------------- */
593     /* Assign the new field information fields. */
594     /* -------------------------------------------------------------------- */
595     psDBF->panFieldOffset[psDBF->nFields-1] = psDBF->nRecordLength;
596     psDBF->nRecordLength += nWidth;
597     psDBF->panFieldSize[psDBF->nFields-1] = nWidth;
598     psDBF->panFieldDecimals[psDBF->nFields-1] = nDecimals;
599    
600     if( eType == FTString )
601     psDBF->pachFieldType[psDBF->nFields-1] = 'C';
602     else
603     psDBF->pachFieldType[psDBF->nFields-1] = 'N';
604    
605     /* -------------------------------------------------------------------- */
606     /* Extend the required header information. */
607     /* -------------------------------------------------------------------- */
608     psDBF->nHeaderLength += 32;
609     psDBF->bUpdated = FALSE;
610    
611     psDBF->pszHeader = (char *) SfRealloc(psDBF->pszHeader,psDBF->nFields*32);
612    
613     pszFInfo = psDBF->pszHeader + 32 * (psDBF->nFields-1);
614    
615     for( i = 0; i < 32; i++ )
616     pszFInfo[i] = '\0';
617    
618     if( (int) strlen(pszFieldName) < 10 )
619     strncpy( pszFInfo, pszFieldName, strlen(pszFieldName));
620     else
621     strncpy( pszFInfo, pszFieldName, 10);
622    
623     pszFInfo[11] = psDBF->pachFieldType[psDBF->nFields-1];
624    
625     if( eType == FTString )
626     {
627     pszFInfo[16] = nWidth % 256;
628     pszFInfo[17] = nWidth / 256;
629     }
630     else
631     {
632     pszFInfo[16] = nWidth;
633     pszFInfo[17] = nDecimals;
634     }
635    
636     /* -------------------------------------------------------------------- */
637     /* Make the current record buffer appropriately larger. */
638     /* -------------------------------------------------------------------- */
639     psDBF->pszCurrentRecord = (char *) SfRealloc(psDBF->pszCurrentRecord,
640     psDBF->nRecordLength);
641    
642     return( psDBF->nFields-1 );
643     }
644    
645     /************************************************************************/
646     /* DBFReadAttribute() */
647     /* */
648     /* Read one of the attribute fields of a record. */
649     /************************************************************************/
650    
651     static void *DBFReadAttribute(DBFHandle psDBF, int hEntity, int iField,
652     char chReqType )
653    
654     {
655     int nRecordOffset;
656     unsigned char *pabyRec;
657     void *pReturnField = NULL;
658    
659     static double dDoubleField;
660    
661     /* -------------------------------------------------------------------- */
662     /* Verify selection. */
663     /* -------------------------------------------------------------------- */
664     if( hEntity < 0 || hEntity >= psDBF->nRecords )
665     return( NULL );
666    
667     if( iField < 0 || iField >= psDBF->nFields )
668     return( NULL );
669    
670     /* -------------------------------------------------------------------- */
671     /* Have we read the record? */
672     /* -------------------------------------------------------------------- */
673     if( psDBF->nCurrentRecord != hEntity )
674     {
675     DBFFlushRecord( psDBF );
676    
677     nRecordOffset = psDBF->nRecordLength * hEntity + psDBF->nHeaderLength;
678    
679     if( fseek( psDBF->fp, nRecordOffset, 0 ) != 0 )
680     {
681     fprintf( stderr, "fseek(%d) failed on DBF file.\n",
682     nRecordOffset );
683     return NULL;
684     }
685    
686     if( fread( psDBF->pszCurrentRecord, psDBF->nRecordLength,
687     1, psDBF->fp ) != 1 )
688     {
689     fprintf( stderr, "fread(%d) failed on DBF file.\n",
690     psDBF->nRecordLength );
691     return NULL;
692     }
693    
694     psDBF->nCurrentRecord = hEntity;
695     }
696    
697     pabyRec = (unsigned char *) psDBF->pszCurrentRecord;
698    
699     /* -------------------------------------------------------------------- */
700     /* Ensure our field buffer is large enough to hold this buffer. */
701     /* -------------------------------------------------------------------- */
702     if( psDBF->panFieldSize[iField]+1 > nStringFieldLen )
703     {
704     nStringFieldLen = psDBF->panFieldSize[iField]*2 + 10;
705     pszStringField = (char *) SfRealloc(pszStringField,nStringFieldLen);
706     }
707    
708     /* -------------------------------------------------------------------- */
709     /* Extract the requested field. */
710     /* -------------------------------------------------------------------- */
711     strncpy( pszStringField,
712     ((const char *) pabyRec) + psDBF->panFieldOffset[iField],
713     psDBF->panFieldSize[iField] );
714     pszStringField[psDBF->panFieldSize[iField]] = '\0';
715    
716     pReturnField = pszStringField;
717    
718     /* -------------------------------------------------------------------- */
719     /* Decode the field. */
720     /* -------------------------------------------------------------------- */
721     if( chReqType == 'N' )
722     {
723     dDoubleField = atof(pszStringField);
724    
725     pReturnField = &dDoubleField;
726     }
727    
728     /* -------------------------------------------------------------------- */
729     /* Should we trim white space off the string attribute value? */
730     /* -------------------------------------------------------------------- */
731     #ifdef TRIM_DBF_WHITESPACE
732     else
733     {
734     char *pchSrc, *pchDst;
735    
736     pchDst = pchSrc = pszStringField;
737     while( *pchSrc == ' ' )
738     pchSrc++;
739    
740     while( *pchSrc != '\0' )
741     *(pchDst++) = *(pchSrc++);
742     *pchDst = '\0';
743    
744     while( pchDst != pszStringField && *(--pchDst) == ' ' )
745     *pchDst = '\0';
746     }
747     #endif
748    
749     return( pReturnField );
750     }
751    
752     /************************************************************************/
753     /* DBFReadIntAttribute() */
754     /* */
755     /* Read an integer attribute. */
756     /************************************************************************/
757    
758     int SHPAPI_CALL
759     DBFReadIntegerAttribute( DBFHandle psDBF, int iRecord, int iField )
760    
761     {
762     double *pdValue;
763    
764     pdValue = (double *) DBFReadAttribute( psDBF, iRecord, iField, 'N' );
765    
766     if( pdValue == NULL )
767     return 0;
768     else
769     return( (int) *pdValue );
770     }
771    
772     /************************************************************************/
773     /* DBFReadDoubleAttribute() */
774     /* */
775     /* Read a double attribute. */
776     /************************************************************************/
777    
778     double SHPAPI_CALL
779     DBFReadDoubleAttribute( DBFHandle psDBF, int iRecord, int iField )
780    
781     {
782     double *pdValue;
783    
784     pdValue = (double *) DBFReadAttribute( psDBF, iRecord, iField, 'N' );
785    
786     if( pdValue == NULL )
787     return 0.0;
788     else
789     return( *pdValue );
790     }
791    
792     /************************************************************************/
793     /* DBFReadStringAttribute() */
794     /* */
795     /* Read a string attribute. */
796     /************************************************************************/
797    
798     const char SHPAPI_CALL1(*)
799     DBFReadStringAttribute( DBFHandle psDBF, int iRecord, int iField )
800    
801     {
802     return( (const char *) DBFReadAttribute( psDBF, iRecord, iField, 'C' ) );
803     }
804    
805     /************************************************************************/
806     /* DBFIsAttributeNULL() */
807     /* */
808     /* Return TRUE if value for field is NULL. */
809     /* */
810     /* Contributed by Jim Matthews. */
811     /************************************************************************/
812    
813     int SHPAPI_CALL
814     DBFIsAttributeNULL( DBFHandle psDBF, int iRecord, int iField )
815    
816     {
817     const char *pszValue;
818    
819     pszValue = DBFReadStringAttribute( psDBF, iRecord, iField );
820    
821     switch(psDBF->pachFieldType[iField])
822     {
823     case 'N':
824     case 'F':
825     /* NULL numeric fields have value "****************" */
826     return pszValue[0] == '*';
827    
828     case 'D':
829     /* NULL date fields have value "00000000" */
830     return strncmp(pszValue,"00000000",8) == 0;
831    
832     case 'L':
833     /* NULL boolean fields have value "?" */
834     return pszValue[0] == '?';
835    
836     default:
837     /* empty string fields are considered NULL */
838     return strlen(pszValue) == 0;
839     }
840     return FALSE;
841     }
842    
843     /************************************************************************/
844     /* DBFGetFieldCount() */
845     /* */
846     /* Return the number of fields in this table. */
847     /************************************************************************/
848    
849     int SHPAPI_CALL
850     DBFGetFieldCount( DBFHandle psDBF )
851    
852     {
853     return( psDBF->nFields );
854     }
855    
856     /************************************************************************/
857     /* DBFGetRecordCount() */
858     /* */
859     /* Return the number of records in this table. */
860     /************************************************************************/
861    
862     int SHPAPI_CALL
863     DBFGetRecordCount( DBFHandle psDBF )
864    
865     {
866     return( psDBF->nRecords );
867     }
868    
869     /************************************************************************/
870     /* DBFGetFieldInfo() */
871     /* */
872     /* Return any requested information about the field. */
873     /************************************************************************/
874    
875     DBFFieldType SHPAPI_CALL
876     DBFGetFieldInfo( DBFHandle psDBF, int iField, char * pszFieldName,
877     int * pnWidth, int * pnDecimals )
878    
879     {
880     if( iField < 0 || iField >= psDBF->nFields )
881     return( FTInvalid );
882    
883     if( pnWidth != NULL )
884     *pnWidth = psDBF->panFieldSize[iField];
885    
886     if( pnDecimals != NULL )
887     *pnDecimals = psDBF->panFieldDecimals[iField];
888    
889     if( pszFieldName != NULL )
890     {
891     int i;
892    
893     strncpy( pszFieldName, (char *) psDBF->pszHeader+iField*32, 11 );
894     pszFieldName[11] = '\0';
895     for( i = 10; i > 0 && pszFieldName[i] == ' '; i-- )
896     pszFieldName[i] = '\0';
897     }
898    
899     if( psDBF->pachFieldType[iField] == 'N'
900     || psDBF->pachFieldType[iField] == 'F'
901     || psDBF->pachFieldType[iField] == 'D' )
902     {
903     if( psDBF->panFieldDecimals[iField] > 0 )
904     return( FTDouble );
905     else
906     return( FTInteger );
907     }
908     else
909     {
910     return( FTString );
911     }
912     }
913    
914     /************************************************************************/
915     /* DBFWriteAttribute() */
916     /* */
917     /* Write an attribute record to the file. */
918     /************************************************************************/
919    
920     static int DBFWriteAttribute(DBFHandle psDBF, int hEntity, int iField,
921     void * pValue )
922    
923     {
924     int nRecordOffset, i, j;
925     unsigned char *pabyRec;
926     char szSField[400], szFormat[20];
927    
928     /* -------------------------------------------------------------------- */
929     /* Is this a valid record? */
930     /* -------------------------------------------------------------------- */
931     if( hEntity < 0 || hEntity > psDBF->nRecords )
932     return( FALSE );
933    
934     if( psDBF->bNoHeader )
935     DBFWriteHeader(psDBF);
936    
937     /* -------------------------------------------------------------------- */
938     /* Is this a brand new record? */
939     /* -------------------------------------------------------------------- */
940     if( hEntity == psDBF->nRecords )
941     {
942     DBFFlushRecord( psDBF );
943    
944     psDBF->nRecords++;
945     for( i = 0; i < psDBF->nRecordLength; i++ )
946     psDBF->pszCurrentRecord[i] = ' ';
947    
948     psDBF->nCurrentRecord = hEntity;
949     }
950    
951     /* -------------------------------------------------------------------- */
952     /* Is this an existing record, but different than the last one */
953     /* we accessed? */
954     /* -------------------------------------------------------------------- */
955     if( psDBF->nCurrentRecord != hEntity )
956     {
957     DBFFlushRecord( psDBF );
958    
959     nRecordOffset = psDBF->nRecordLength * hEntity + psDBF->nHeaderLength;
960    
961     fseek( psDBF->fp, nRecordOffset, 0 );
962     fread( psDBF->pszCurrentRecord, psDBF->nRecordLength, 1, psDBF->fp );
963    
964     psDBF->nCurrentRecord = hEntity;
965     }
966    
967     pabyRec = (unsigned char *) psDBF->pszCurrentRecord;
968    
969     psDBF->bCurrentRecordModified = TRUE;
970     psDBF->bUpdated = TRUE;
971    
972     /* -------------------------------------------------------------------- */
973     /* Translate NULL value to valid DBF file representation. */
974     /* */
975     /* Contributed by Jim Matthews. */
976     /* -------------------------------------------------------------------- */
977     if( pValue == NULL )
978     {
979     switch(psDBF->pachFieldType[iField])
980     {
981     case 'N':
982     case 'F':
983     /* NULL numeric fields have value "****************" */
984     memset( (char *) (pabyRec+psDBF->panFieldOffset[iField]), '*',
985     psDBF->panFieldSize[iField] );
986     break;
987    
988     case 'D':
989     /* NULL date fields have value "00000000" */
990     memset( (char *) (pabyRec+psDBF->panFieldOffset[iField]), '0',
991     psDBF->panFieldSize[iField] );
992     break;
993    
994     case 'L':
995     /* NULL boolean fields have value "?" */
996     memset( (char *) (pabyRec+psDBF->panFieldOffset[iField]), '?',
997     psDBF->panFieldSize[iField] );
998     break;
999    
1000     default:
1001     /* empty string fields are considered NULL */
1002     memset( (char *) (pabyRec+psDBF->panFieldOffset[iField]), '\0',
1003     psDBF->panFieldSize[iField] );
1004     break;
1005     }
1006     return TRUE;
1007     }
1008    
1009     /* -------------------------------------------------------------------- */
1010     /* Assign all the record fields. */
1011     /* -------------------------------------------------------------------- */
1012     switch( psDBF->pachFieldType[iField] )
1013     {
1014     case 'D':
1015     case 'N':
1016     case 'F':
1017     if( psDBF->panFieldDecimals[iField] == 0 )
1018     {
1019     int nWidth = psDBF->panFieldSize[iField];
1020    
1021     if( sizeof(szSField)-2 < nWidth )
1022     nWidth = sizeof(szSField)-2;
1023    
1024     sprintf( szFormat, "%%%dd", nWidth );
1025     sprintf(szSField, szFormat, (int) *((double *) pValue) );
1026     if( (int)strlen(szSField) > psDBF->panFieldSize[iField] )
1027     szSField[psDBF->panFieldSize[iField]] = '\0';
1028    
1029     strncpy((char *) (pabyRec+psDBF->panFieldOffset[iField]),
1030     szSField, strlen(szSField) );
1031     }
1032     else
1033     {
1034     int nWidth = psDBF->panFieldSize[iField];
1035    
1036     if( sizeof(szSField)-2 < nWidth )
1037     nWidth = sizeof(szSField)-2;
1038    
1039     sprintf( szFormat, "%%%d.%df",
1040     nWidth, psDBF->panFieldDecimals[iField] );
1041     sprintf(szSField, szFormat, *((double *) pValue) );
1042     if( (int) strlen(szSField) > psDBF->panFieldSize[iField] )
1043     szSField[psDBF->panFieldSize[iField]] = '\0';
1044     strncpy((char *) (pabyRec+psDBF->panFieldOffset[iField]),
1045     szSField, strlen(szSField) );
1046     }
1047     break;
1048    
1049     default:
1050     if( (int) strlen((char *) pValue) > psDBF->panFieldSize[iField] )
1051     j = psDBF->panFieldSize[iField];
1052     else
1053     {
1054     memset( pabyRec+psDBF->panFieldOffset[iField], ' ',
1055     psDBF->panFieldSize[iField] );
1056     j = strlen((char *) pValue);
1057     }
1058    
1059     strncpy((char *) (pabyRec+psDBF->panFieldOffset[iField]),
1060     (char *) pValue, j );
1061     break;
1062     }
1063    
1064     return( TRUE );
1065     }
1066    
1067     /************************************************************************/
1068     /* DBFWriteDoubleAttribute() */
1069     /* */
1070     /* Write a double attribute. */
1071     /************************************************************************/
1072    
1073     int SHPAPI_CALL
1074     DBFWriteDoubleAttribute( DBFHandle psDBF, int iRecord, int iField,
1075     double dValue )
1076    
1077     {
1078     return( DBFWriteAttribute( psDBF, iRecord, iField, (void *) &dValue ) );
1079     }
1080    
1081     /************************************************************************/
1082     /* DBFWriteIntegerAttribute() */
1083     /* */
1084     /* Write a integer attribute. */
1085     /************************************************************************/
1086    
1087     int SHPAPI_CALL
1088     DBFWriteIntegerAttribute( DBFHandle psDBF, int iRecord, int iField,
1089     int nValue )
1090    
1091     {
1092     double dValue = nValue;
1093    
1094     return( DBFWriteAttribute( psDBF, iRecord, iField, (void *) &dValue ) );
1095     }
1096    
1097     /************************************************************************/
1098     /* DBFWriteStringAttribute() */
1099     /* */
1100     /* Write a string attribute. */
1101     /************************************************************************/
1102    
1103     int SHPAPI_CALL
1104     DBFWriteStringAttribute( DBFHandle psDBF, int iRecord, int iField,
1105     const char * pszValue )
1106    
1107     {
1108     return( DBFWriteAttribute( psDBF, iRecord, iField, (void *) pszValue ) );
1109     }
1110    
1111     /************************************************************************/
1112     /* DBFWriteNULLAttribute() */
1113     /* */
1114     /* Write a string attribute. */
1115     /************************************************************************/
1116    
1117     int SHPAPI_CALL
1118     DBFWriteNULLAttribute( DBFHandle psDBF, int iRecord, int iField )
1119    
1120     {
1121     return( DBFWriteAttribute( psDBF, iRecord, iField, NULL ) );
1122     }
1123    
1124     /************************************************************************/
1125     /* DBFWriteTuple() */
1126     /* */
1127     /* Write an attribute record to the file. */
1128     /************************************************************************/
1129    
1130     int SHPAPI_CALL
1131     DBFWriteTuple(DBFHandle psDBF, int hEntity, void * pRawTuple )
1132    
1133     {
1134     int nRecordOffset, i;
1135     unsigned char *pabyRec;
1136    
1137     /* -------------------------------------------------------------------- */
1138     /* Is this a valid record? */
1139     /* -------------------------------------------------------------------- */
1140     if( hEntity < 0 || hEntity > psDBF->nRecords )
1141     return( FALSE );
1142    
1143     if( psDBF->bNoHeader )
1144     DBFWriteHeader(psDBF);
1145    
1146     /* -------------------------------------------------------------------- */
1147     /* Is this a brand new record? */
1148     /* -------------------------------------------------------------------- */
1149     if( hEntity == psDBF->nRecords )
1150     {
1151     DBFFlushRecord( psDBF );
1152    
1153     psDBF->nRecords++;
1154     for( i = 0; i < psDBF->nRecordLength; i++ )
1155     psDBF->pszCurrentRecord[i] = ' ';
1156    
1157     psDBF->nCurrentRecord = hEntity;
1158     }
1159    
1160     /* -------------------------------------------------------------------- */
1161     /* Is this an existing record, but different than the last one */
1162     /* we accessed? */
1163     /* -------------------------------------------------------------------- */
1164     if( psDBF->nCurrentRecord != hEntity )
1165     {
1166     DBFFlushRecord( psDBF );
1167    
1168     nRecordOffset = psDBF->nRecordLength * hEntity + psDBF->nHeaderLength;
1169    
1170     fseek( psDBF->fp, nRecordOffset, 0 );
1171     fread( psDBF->pszCurrentRecord, psDBF->nRecordLength, 1, psDBF->fp );
1172    
1173     psDBF->nCurrentRecord = hEntity;
1174     }
1175    
1176     pabyRec = (unsigned char *) psDBF->pszCurrentRecord;
1177    
1178     memcpy ( pabyRec, pRawTuple, psDBF->nRecordLength );
1179    
1180     psDBF->bCurrentRecordModified = TRUE;
1181     psDBF->bUpdated = TRUE;
1182    
1183     return( TRUE );
1184     }
1185    
1186     /************************************************************************/
1187     /* DBFReadTuple() */
1188     /* */
1189     /* Read one of the attribute fields of a record. */
1190     /************************************************************************/
1191    
1192     const char SHPAPI_CALL1(*)
1193     DBFReadTuple(DBFHandle psDBF, int hEntity )
1194    
1195     {
1196     int nRecordOffset;
1197     unsigned char *pabyRec;
1198     static char *pReturnTuple = NULL;
1199    
1200     static int nTupleLen = 0;
1201    
1202     /* -------------------------------------------------------------------- */
1203     /* Have we read the record? */
1204     /* -------------------------------------------------------------------- */
1205     if( hEntity < 0 || hEntity >= psDBF->nRecords )
1206     return( NULL );
1207    
1208     if( psDBF->nCurrentRecord != hEntity )
1209     {
1210     DBFFlushRecord( psDBF );
1211    
1212     nRecordOffset = psDBF->nRecordLength * hEntity + psDBF->nHeaderLength;
1213    
1214     fseek( psDBF->fp, nRecordOffset, 0 );
1215     fread( psDBF->pszCurrentRecord, psDBF->nRecordLength, 1, psDBF->fp );
1216    
1217     psDBF->nCurrentRecord = hEntity;
1218     }
1219    
1220     pabyRec = (unsigned char *) psDBF->pszCurrentRecord;
1221    
1222     if ( nTupleLen < psDBF->nRecordLength) {
1223     nTupleLen = psDBF->nRecordLength;
1224     pReturnTuple = (char *) SfRealloc(pReturnTuple, psDBF->nRecordLength);
1225     }
1226    
1227     memcpy ( pReturnTuple, pabyRec, psDBF->nRecordLength );
1228    
1229     return( pReturnTuple );
1230     }
1231    
1232     /************************************************************************/
1233     /* DBFCloneEmpty() */
1234     /* */
1235     /* Read one of the attribute fields of a record. */
1236     /************************************************************************/
1237    
1238     DBFHandle SHPAPI_CALL
1239     DBFCloneEmpty(DBFHandle psDBF, const char * pszFilename )
1240     {
1241     DBFHandle newDBF;
1242    
1243     newDBF = DBFCreate ( pszFilename );
1244     if ( newDBF == NULL ) return ( NULL );
1245    
1246     newDBF->pszHeader = (void *) malloc ( 32 * psDBF->nFields );
1247     memcpy ( newDBF->pszHeader, psDBF->pszHeader, 32 * psDBF->nFields );
1248    
1249     newDBF->nFields = psDBF->nFields;
1250     newDBF->nRecordLength = psDBF->nRecordLength;
1251     newDBF->nHeaderLength = psDBF->nHeaderLength;
1252    
1253     newDBF->panFieldOffset = (void *) malloc ( sizeof(int) * psDBF->nFields );
1254     memcpy ( newDBF->panFieldOffset, psDBF->panFieldOffset, sizeof(int) * psDBF->nFields );
1255     newDBF->panFieldSize = (void *) malloc ( sizeof(int) * psDBF->nFields );
1256     memcpy ( newDBF->panFieldSize, psDBF->panFieldSize, sizeof(int) * psDBF->nFields );
1257     newDBF->panFieldDecimals = (void *) malloc ( sizeof(int) * psDBF->nFields );
1258     memcpy ( newDBF->panFieldDecimals, psDBF->panFieldDecimals, sizeof(int) * psDBF->nFields );
1259     newDBF->pachFieldType = (void *) malloc ( sizeof(int) * psDBF->nFields );
1260     memcpy ( newDBF->pachFieldType, psDBF->pachFieldType, sizeof(int) * psDBF->nFields );
1261    
1262     newDBF->bNoHeader = TRUE;
1263     newDBF->bUpdated = TRUE;
1264    
1265     DBFWriteHeader ( newDBF );
1266     DBFClose ( newDBF );
1267    
1268     newDBF = DBFOpen ( pszFilename, "rb+" );
1269    
1270     return ( newDBF );
1271     }
1272    
1273     /************************************************************************/
1274     /* DBFGetNativeFieldType() */
1275     /* */
1276     /* Return the DBase field type for the specified field. */
1277     /* */
1278     /* Value can be one of: 'C' (String), 'D' (Date), 'F' (Float), */
1279     /* 'N' (Numeric, with or without decimal), */
1280     /* 'L' (Logical), */
1281     /* 'M' (Memo: 10 digits .DBT block ptr) */
1282     /************************************************************************/
1283    
1284     char SHPAPI_CALL
1285     DBFGetNativeFieldType( DBFHandle psDBF, int iField )
1286    
1287     {
1288     if( iField >=0 && iField < psDBF->nFields )
1289     return psDBF->pachFieldType[iField];
1290    
1291     return ' ';
1292     }
1293    
1294     /************************************************************************/
1295     /* str_to_upper() */
1296     /************************************************************************/
1297    
1298     static void str_to_upper (char *string)
1299     {
1300     int len;
1301     short i = -1;
1302    
1303     len = strlen (string);
1304    
1305     while (++i < len)
1306     if (isalpha(string[i]) && islower(string[i]))
1307     string[i] = toupper ((int)string[i]);
1308     }
1309    
1310     /************************************************************************/
1311     /* DBFGetFieldIndex() */
1312     /* */
1313     /* Get the index number for a field in a .dbf file. */
1314     /* */
1315     /* Contributed by Jim Matthews. */
1316     /************************************************************************/
1317    
1318     int SHPAPI_CALL
1319     DBFGetFieldIndex(DBFHandle psDBF, const char *pszFieldName)
1320    
1321     {
1322     char name[12], name1[12], name2[12];
1323     int i;
1324    
1325     strncpy(name1, pszFieldName,11);
1326     str_to_upper(name1);
1327    
1328     for( i = 0; i < DBFGetFieldCount(psDBF); i++ )
1329     {
1330     DBFGetFieldInfo( psDBF, i, name, NULL, NULL );
1331     strncpy(name2,name,11);
1332     str_to_upper(name2);
1333    
1334     if(!strncmp(name1,name2,10))
1335     return(i);
1336     }
1337     return(-1);
1338     }
1339    
1340     /************************************************************************/
1341     /* DBFCommit() */
1342     /* */
1343     /* Write any changes made into the file. */
1344     /* */
1345     /************************************************************************/
1346     int SHPAPI_CALL
1347     DBFCommit( DBFHandle psDBF )
1348    
1349     {
1350     DBFFlushRecord( psDBF );
1351     if (fflush( psDBF->fp ) == EOF)
1352     return FALSE;
1353    
1354     return TRUE;
1355     }

Properties

Name Value
svn:eol-style native
svn:keywords Author Date Id Revision

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26