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

Diff of /branches/WIP-pyshapelib-bramz/libraries/pyshapelib/dbflibmodule.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

trunk/thuban/libraries/pyshapelib/dbflib.i revision 1917 by bh, Mon Nov 3 17:31:11 2003 UTC branches/WIP-pyshapelib-bramz/libraries/pyshapelib/dbflibmodule.c revision 2753 by bramz, Wed Apr 11 18:57:04 2007 UTC
# Line 1  Line 1 
1  /* SWIG (www.swig.org) interface file for the dbf interface of shapelib  /* Copyright (c) 2001, 2002, 2007 by Intevation GmbH
2     * Authors:
3     * Bram de Greve <[email protected]>
4     * Bernhard Herzog <[email protected]>
5   *   *
6   * At the moment (Dec 2000) this file is only useful to generate Python   * This program is free software under the GPL (>=v2)
7   * bindings. Invoke swig as follows:   * Read the file COPYING coming with Thuban for details.
8     */
9    
10    #include "pyshapelib_common.h"
11    
12    /* UNICODE & LANGUAGE DRIVER SUPPORT FOR DBFLIB
13   *   *
14   *      swig -python -shadow dbflib.i   * When writing Unicode objects to a dbflib database, the unicode has to be
15     * encoded in 8-bit characters using a code page.  This code page is indentified
16     * by the Language Driver ID (LDID) field in the database header.
17   *   *
18   * to generate dbflib_wrap.c and dbflib.py. dbflib_wrap.c defines a   * At this moment, this need unofficial modifications of the maptools shapelib
19   * bunch of Python-functions that wrap the appripriate dbflib functions   * library because they do not read the LDID.  No patch has been submitted yet,
20   * and dbflib.py contains an object oriented wrapper around   * but the version contained in the Thuban source tree incorporates the required
21   * dbflib_wrap.c.   * modifications.
22   *   *
23   * This module defines one object type: DBFFile.   * pyshapelib is designed to compile with either the patched or unpatched shapelib
24     * by defining HAVE_LANGUAGE_DRIVER as true or false respectively.  In the latter
25     * case, a Windows ANSI code page (cp1252) is assumed
26   */   */
27     #if HAVE_LANGUAGE_DRIVER
28    
29    #define PYSHAPELIB_NUM_LANGUAGE_DRIVERS 256
30    
31    #define PYSHAPELIB_ADD_LANGUAGE_DRIVER(ldid, codec, name)\
32            codecs[ldid] = codec;\
33            drivers[ldid] = "LDID_" name;\
34            PyModule_AddIntConstant(module, "LDID_" name, ldid)
35    
36    static char* codecs[PYSHAPELIB_NUM_LANGUAGE_DRIVERS];
37    static char* drivers[PYSHAPELIB_NUM_LANGUAGE_DRIVERS];
38    
39    #endif
40    
 /* this is the dbflib module */  
 %module dbflib  
41    
42  /* first a %{,%} block. These blocks are copied verbatim to the  
43   * dbflib_wrap.c file and are not parsed by SWIG. This is the place to  /** Determine name of Python's built-in codec
  * import headerfiles and define helper-functions that are needed by the  
  * automatically generated wrappers.  
44   */   */
45    static char* get_codec(DBFHandle handle)
46    {
47    #if HAVE_LANGUAGE_DRIVER
48            if (!codecs[handle->nLanguageDriver])
49            {
50                    PyErr_Format(PyExc_ValueError, "Language Driver ID %d not recognized", handle->nLanguageDriver);
51            }
52            return codecs[handle->nLanguageDriver];
53    #else
54            return "cp1252";
55    #endif
56    }
57    
 %{  
 #include "shapefil.h"  
58    
59    
60  /* Read one attribute from the dbf handle and return it as a new python object  /** decode to unicode object
  *  
  * If an error occurs, set the appropriate Python exception and return  
  * NULL.  
  *  
  * Assume that the values of the record and field arguments are valid.  
  * The name argument will be passed to DBFGetFieldInfo as is and should  
  * thus be either NULL or a pointer to an array of at least 12 chars  
61   */   */
62  static PyObject *  static PyObject* decode_string(DBFHandle handle, const char* string)
 do_read_attribute(DBFInfo * handle, int record, int field, char * name)  
63  {  {
64      int type, width;          char* codec = get_codec(handle);
65      PyObject *value;          if (!codec) return NULL;
66            return PyUnicode_Decode(string, strlen(string), codec, NULL);
67    }
68    
69      type = DBFGetFieldInfo(handle, field, name, &width, NULL);  /** encode unicode object to normal Python string object
70      /* For strings NULL and the empty string are indistinguishable   */
71       * in DBF files. We prefer empty strings instead for backwards  static PyObject* encode_string(DBFHandle handle, PyObject* string)
72       * compatibility reasons because older wrapper versions returned  {
73       * emtpy strings as empty strings.          char* codec = get_codec(handle);
74       */          if (!codec) return NULL;
75      if (type != FTString && DBFIsAttributeNULL(handle, record, field))  
76      {          if (PyString_Check(string))
77          value = Py_None;          {
78          Py_INCREF(value);                  return PyString_AsEncodedObject(string, codec, NULL);
     }  
     else  
     {  
         switch (type)  
         {  
         case FTString:  
         {  
             const char * temp = DBFReadStringAttribute(handle, record, field);  
             if (temp)  
             {  
                 value = PyString_FromString(temp);  
             }  
             else  
             {  
                 PyErr_Format(PyExc_IOError,  
                              "Can't read value for row %d column %d",  
                              record, field);  
                 value = NULL;  
             }  
             break;  
79          }          }
80          case FTInteger:          if (PyUnicode_Check(string))
81              value = PyInt_FromLong(DBFReadIntegerAttribute(handle, record,          {
82                                                             field));                  return PyUnicode_AsEncodedString(string, codec, NULL);
             break;  
         case FTDouble:  
             value = PyFloat_FromDouble(DBFReadDoubleAttribute(handle, record,  
                                                               field));  
             break;  
         default:  
             PyErr_Format(PyExc_TypeError, "Invalid field data type %d",  
                          type);  
             value = NULL;  
83          }          }
84      }  
85      if (!value)          PyErr_SetString(PyExc_TypeError, "value is neither a string or unicode object");
86          return NULL;          return NULL;
87    }
88    
     return value;  
 }      
89    
 /* the read_attribute method. Return the value of the given record and  
  * field as a python object of the appropriate type.  
  *  
  * In case of error, set a python exception and return NULL. Since that  
  * value will be returned to the python interpreter as is, the  
  * interpreter should recognize the exception.  
  */  
90    
91  static PyObject *  /* --- DBFFile ------------------------------------------------------------------------------------------------------- */
92  DBFInfo_read_attribute(DBFInfo * handle, int record, int field)  
93    typedef struct {
94            PyObject_HEAD
95            DBFHandle handle;
96    } DBFFileObject;
97    
98    
99    
100    /* allocator
101    */
102    static PyObject* dbffile_new(PyTypeObject* type, PyObject* args, PyObject* kwds)
103  {  {
104      if (record < 0 || record >= DBFGetRecordCount(handle))          DBFFileObject* self;    
105      {          self = (DBFFileObject*) type->tp_alloc(type, 0);
106          PyErr_Format(PyExc_ValueError,          self->handle = NULL;
107                       "record index %d out of bounds (record count: %d)",          return (PyObject*) self;
108                       record, DBFGetRecordCount(handle));  }
109          return NULL;  
     }  
110    
     if (field < 0 || field >= DBFGetFieldCount(handle))  
     {  
         PyErr_Format(PyExc_ValueError,  
                      "field index %d out of bounds (field count: %d)",  
                      field, DBFGetFieldCount(handle));  
         return NULL;  
     }  
111    
112      return do_read_attribute(handle, record, field, NULL);  /* deallocator
113    */
114    static void dbffile_dealloc(DBFFileObject* self)
115    {
116            DBFClose(self->handle);
117            self->handle = NULL;
118            self->ob_type->tp_free((PyObject*)self);
119  }  }
       
120    
 /* the read_record method. Return the record record as a dictionary with  
  * whose keys are the names of the fields, and their values as the  
  * appropriate Python type.  
  *  
  * In case of error, set a python exception and return NULL. Since that  
  * value will be returned to the python interpreter as is, the  
  * interpreter should recognize the exception.  
  */  
121    
122  static PyObject *  
123  DBFInfo_read_record(DBFInfo * handle, int record)  /* constructor
124    */
125    static int dbffile_init(DBFFileObject* self, PyObject* args, PyObject* kwds)
126  {  {
127      int num_fields;          char* file = NULL;
128      int i;          char* mode = "rb";
129      int type, width;          static char *kwlist[] = {"name", "mode", NULL};
130      char name[12];  
131      PyObject *dict;          DBFClose(self->handle);
132      PyObject *value;          self->handle = NULL;
133    
134      if (record < 0 || record >= DBFGetRecordCount(handle))  #if defined(SHPAPI_HAS_WIDE) && defined(Py_WIN_WIDE_FILENAMES)
135      {          if (GetVersion() < 0x80000000) {    /* On NT, so wide API available */
136          PyErr_Format(PyExc_ValueError,                  PyObject *wfile;
137                       "record index %d out of bounds (record count: %d)",                  if (PyArg_ParseTupleAndKeywords(args, kwds, "U|s:DBFFile", kwlist, &wfile, &mode))
138                       record, DBFGetRecordCount(handle));                  {
139          return NULL;                          PyObject *wmode = PyUnicode_DecodeASCII(mode, strlen(mode), NULL);
140      }                          if (!wmode) return -1;
141                            self->handle = DBFOpenW(PyUnicode_AS_UNICODE(wfile), PyUnicode_AS_UNICODE(wmode));
142                            Py_DECREF(wmode);
143                            if (!self->handle)
144                            {
145                                    PyErr_SetFromErrnoWithFilenameObject(PyExc_IOError, wfile);
146                                    return -1;
147                            }
148                    }
149                    else
150                    {
151                            /* Drop the argument parsing error as narrow
152                               strings are also valid. */
153                            PyErr_Clear();
154                    }
155            }
156    #endif
157    
158            if (!self->handle)
159            {
160                    if (!PyArg_ParseTupleAndKeywords(args, kwds, "et|s:DBFFile", kwlist,
161                            Py_FileSystemDefaultEncoding, &file, &mode)) return -1;
162                    self->handle = DBFOpen(file, mode);
163    
164                    if (!self->handle)
165                    {
166                            PyErr_SetFromErrnoWithFilename(PyExc_IOError, file);
167                            PyMem_Free(file);
168                            return -1;
169                    }
170    
171                    PyMem_Free(file);
172            }
173    
174            return 0;
175    }
176    
177    
178    
179    static PyObject* dbffile_close(DBFFileObject* self)
180    {
181            DBFClose(self->handle);
182            self->handle = NULL;
183            Py_RETURN_NONE;
184    }
185    
186    
187    
188    static PyObject* dbffile_field_count(DBFFileObject* self)
189    {
190            return PyInt_FromLong((long)DBFGetFieldCount(self->handle));
191    }
192    
193    
194    
195    static PyObject* dbffile_record_count(DBFFileObject* self)
196    {
197            return PyInt_FromLong((long)DBFGetRecordCount(self->handle));
198    }
199    
200    
201    
202    static PyObject* dbffile_field_info(DBFFileObject* self, PyObject* args)
203    {
204            char field_name[12];
205            int field, width = 0, decimals = 0, field_type;
206            PyObject* name_object = NULL;
207            
208            if (!PyArg_ParseTuple(args, "i:field_info", &field)) return NULL;
209            
210            field_name[0] = '\0';
211            field_type = DBFGetFieldInfo(self->handle, field, field_name, &width, &decimals);
212            name_object = decode_string(self->handle, field_name);
213            
214            return Py_BuildValue("iOii", field_type, name_object, width, decimals);
215    }
216    
217    
218    
219    static PyObject* dbffile_add_field(DBFFileObject* self, PyObject* args)
220    {
221            PyObject *oname = NULL, *name = NULL;
222            int type, width, decimals;
223            int field;
224            
225            if (!PyArg_ParseTuple(args, "Uiii:add_field", &oname, &type, &width, &decimals)
226                    && !PyArg_ParseTuple(args, "Siii:add_field", &oname, &type, &width, &decimals)) return NULL;
227            
228            name = encode_string(self->handle, oname);
229            if (!name) return NULL;
230    
231            field = DBFAddField(self->handle, PyString_AsString(name), (DBFFieldType)type, width, decimals);
232            Py_DECREF(name);
233            
234            if (field < 0)
235            {
236                    PyErr_SetString(PyExc_ValueError, "Failed to add field due to inappropriate field definition");
237                    return NULL;
238            }
239            return PyInt_FromLong((long)field);
240    }
241    
242    
243      dict = PyDict_New();  
244      if (!dict)  /* Read one attribute from the dbf handle and return it as a new python object
245    *
246    * If an error occurs, set the appropriate Python exception and return
247    * NULL.
248    *
249    * Assume that the values of the record and field arguments are valid.
250    * The name argument will be passed to DBFGetFieldInfo as is and should
251    * thus be either NULL or a pointer to an array of at least 12 chars
252    */
253    static PyObject* do_read_attribute(DBFHandle handle, int record, int field, char * name)
254    {
255            int type, width;
256            const char* string;
257            type = DBFGetFieldInfo(handle, field, name, &width, NULL);
258            
259            /* For strings NULL and the empty string are indistinguishable
260            * in DBF files. We prefer empty strings instead for backwards
261            * compatibility reasons because older wrapper versions returned
262            * emtpy strings as empty strings.
263            */
264            if (type != FTString && DBFIsAttributeNULL(handle, record, field))
265            {
266                    Py_RETURN_NONE;
267            }
268            else
269            {
270                    switch (type)
271                    {
272                    case FTString:
273                            string = DBFReadStringAttribute(handle, record, field);
274                            if (string) return decode_string(handle, string);
275    
276                    case FTInteger:
277                            return PyInt_FromLong((long)DBFReadIntegerAttribute(handle, record, field));
278    
279                    case FTDouble:
280                            return PyFloat_FromDouble(DBFReadDoubleAttribute(handle, record, field));
281                            
282                    case FTLogical:
283                            string = DBFReadLogicalAttribute(handle, record, field);
284                            if (string)
285                            {
286                                    switch (string[0])
287                                    {
288                                    case 'F':
289                                    case 'N':
290                                            Py_RETURN_FALSE;
291                                    case 'T':
292                                    case 'Y':
293                                            Py_RETURN_TRUE;
294                                    }
295                            }
296                            break;
297    
298                    default:
299                            PyErr_Format(PyExc_TypeError, "Invalid field data type %d", type);
300                            return NULL;
301                    }
302            }
303            
304            PyErr_Format(PyExc_IOError,     "Can't read value for row %d column %d", record, field);
305          return NULL;          return NULL;
306    }    
307    
308    
309    
310    /* the read_attribute method. Return the value of the given record and
311    * field as a python object of the appropriate type.
312    */
313    static PyObject* dbffile_read_attribute(DBFFileObject* self, PyObject* args)
314    {
315            int record, field;
316    
317            if (!PyArg_ParseTuple(args, "ii:read_field", &record, &field)) return NULL;
318                    
319      num_fields = DBFGetFieldCount(handle);          if (record < 0 || record >= DBFGetRecordCount(self->handle))
320      for (i = 0; i < num_fields; i++)          {
321      {                  PyErr_Format(PyExc_ValueError,
322          value = do_read_attribute(handle, record, i, name);                                  "record index %d out of bounds (record count: %d)",
323          if (!value)                                  record, DBFGetRecordCount(self->handle));
324              goto fail;                  return NULL;
325            }
326          PyDict_SetItemString(dict, name, value);  
327          Py_DECREF(value);          if (field < 0 || field >= DBFGetFieldCount(self->handle))
328      }          {
329                    PyErr_Format(PyExc_ValueError,
330      return dict;                                  "field index %d out of bounds (field count: %d)",
331                                    field, DBFGetFieldCount(self->handle));
332   fail:                  return NULL;
333      Py_XDECREF(dict);          }
334      return NULL;  
335            return do_read_attribute(self->handle, record, field, NULL);
336  }  }
337    
 /* the write_record method. Write the record record given wither as a  
  * dictionary or a sequence (i.e. a list or a tuple).  
  *  
  * If it's a dictionary the keys must be the names of the fields and  
  * their value must have a suitable type. Only the fields actually  
  * contained in the dictionary are written. Fields for which there's no  
  * item in the dict are not modified.  
  *  
  * If it's a sequence, all fields must be present in the right order.  
  *  
  * In case of error, set a python exception and return NULL. Since that  
  * value will be returned to the python interpreter as is, the  
  * interpreter should recognize the exception.  
  *  
  * The method is implemented with two c-functions, write_field to write  
  * a single field and DBFInfo_write_record as the front-end.  
  */  
338    
339    
340  /* write a single field of a record. */  /* the read_record method. Return the record record as a dictionary with
341  static int  * whose keys are the names of the fields, and their values as the
342  write_field(DBFHandle handle, int record, int field, int type,  * appropriate Python type.
343              PyObject * value)  */
344  {  static PyObject* dbffile_read_record(DBFFileObject* self, PyObject* args)
345      char * string_value;  {
346      int int_value;          int record;
347      double double_value;          int num_fields;
348            int i;
349      if (value == Py_None)          char name[12];
350      {          PyObject *dict;
351          if (!DBFWriteNULLAttribute(handle, record, field))          PyObject *value = NULL;
352          {  
353              PyErr_Format(PyExc_IOError,          if (!PyArg_ParseTuple(args, "i:read_record", &record)) return NULL;
354                           "can't write NULL field %d of record %d",  
355                           field, record);          if (record < 0 || record >= DBFGetRecordCount(self->handle))
             return 0;  
         }  
     }  
     else  
     {  
         switch (type)  
         {  
         case FTString:  
             string_value = PyString_AsString(value);  
             if (!string_value)  
                 return 0;  
             if (!DBFWriteStringAttribute(handle, record, field, string_value))  
             {  
                 PyErr_Format(PyExc_IOError,  
                              "can't write field %d of record %d",  
                              field, record);  
                 return 0;  
             }  
             break;  
   
         case FTInteger:  
             int_value = PyInt_AsLong(value);  
             if (int_value == -1 && PyErr_Occurred())  
                 return 0;  
             if (!DBFWriteIntegerAttribute(handle, record, field, int_value))  
             {  
                 PyErr_Format(PyExc_IOError,  
                              "can't write field %d of record %d",  
                              field, record);  
                 return 0;  
             }  
             break;  
   
         case FTDouble:  
             double_value = PyFloat_AsDouble(value);  
             if (double_value == -1 && PyErr_Occurred())  
                 return 0;  
             if (!DBFWriteDoubleAttribute(handle, record, field, double_value))  
             {  
                 PyErr_Format(PyExc_IOError,  
                              "can't write field %d of record %d",  
                              field, record);  
                 return 0;  
             }  
             break;  
   
         default:  
             PyErr_Format(PyExc_TypeError, "Invalid field data type %d", type);  
             return 0;  
         }  
     }  
   
     return 1;  
 }  
   
 static  
 PyObject *  
 DBFInfo_write_record(DBFHandle handle, int record, PyObject *record_object)  
 {  
     int num_fields;  
     int i, length;  
     int type, width;  
     char name[12];  
     PyObject * value = NULL;  
   
     num_fields = DBFGetFieldCount(handle);  
   
     /* We used to use PyMapping_Check to test whether record_object is a  
      * dictionary like object instead of PySequence_Check to test  
      * whether it's a sequence. Unfortunately in Python 2.3  
      * PyMapping_Check returns true for lists and tuples too so the old  
      * approach doesn't work anymore.  
      */  
     if (PySequence_Check(record_object))  
     {  
         /* It's a sequence object. Iterate through all items in the  
          * sequence and write them to the appropriate field.  
          */  
         length = PySequence_Length(record_object);  
         if (length != num_fields)  
356          {          {
357              PyErr_SetString(PyExc_TypeError,                  PyErr_Format(PyExc_ValueError,
358                              "record must have one item for each field");                          "record index %d out of bounds (record count: %d)",
359              goto fail;                          record, DBFGetRecordCount(self->handle));
360          }                  return NULL;
361          for (i = 0; i < length; i++)          }
362          {  
363              type = DBFGetFieldInfo(handle, i, name, &width, NULL);          dict = PyDict_New();
364              value = PySequence_GetItem(record_object, i);          if (!dict) return NULL;
365              if (value)          
366              {          num_fields = DBFGetFieldCount(self->handle);
                 if (!write_field(handle, record, i, type, value))  
                     goto fail;  
                 Py_DECREF(value);  
             }  
             else  
             {  
                 goto fail;  
             }  
         }  
     }  
     else  
     {  
         /* It's a dictionary-like object. Iterate over the names of the  
          * known fields and write the corresponding item  
          */  
367          for (i = 0; i < num_fields; i++)          for (i = 0; i < num_fields; i++)
368          {          {
369              type = DBFGetFieldInfo(handle, i, name, &width, NULL);                  value = do_read_attribute(self->handle, record, i, name);
370                    if (!value || PyDict_SetItemString(dict, name, value) < 0) goto fail;
             /* if the dictionary has the key name write that object to  
              * the appropriate field, other wise just clear the python  
              * exception and do nothing.  
              */  
             value = PyMapping_GetItemString(record_object, name);  
             if (value)  
             {  
                 if (!write_field(handle, record, i, type, value))  
                     goto fail;  
371                  Py_DECREF(value);                  Py_DECREF(value);
372              }                  value = NULL;
             else  
             {  
                 PyErr_Clear();  
             }  
373          }          }
     }  
374    
375      Py_INCREF(Py_None);          return dict;
     return Py_None;  
376    
377   fail:  fail:
378      Py_XDECREF(value);          Py_XDECREF(value);
379      return NULL;          Py_DECREF(dict);
380            return NULL;
381  }  }
 %}  
382    
383    
 /*  
  * The SWIG Interface definition.  
  */  
384    
385  /* include some common SWIG type definitions and standard exception  /* write a single field of a record. */
386     handling code */  static int do_write_attribute(DBFHandle handle, int record, int field, int type, PyObject* value)
387  %include typemaps.i  {
388  %include exception.i          PyObject* string_value = NULL;
389            int int_value;
390  /* As for ShapeFile in shapelib.i, We define a new C-struct that holds          double double_value;
391   * the DBFHandle. This is mainly done so we can separate the close()          int logical_value;
  * method from the destructor but it also helps with exception handling.  
  *  
  * After the DBFFile has been opened or created the handle is not NULL.  
  * The close() method closes the file and sets handle to NULL as an  
  * indicator that the file has been closed.  
  */  
392    
393  %{          if (value == Py_None)
394      typedef struct {          {
395          DBFHandle handle;                  if (DBFWriteNULLAttribute(handle, record, field)) return 1;
396      } DBFFile;          }
397  %}          else
398            {
399                    switch (type)
400                    {
401                    case FTString:
402                            string_value = encode_string(handle, value);
403                            if (!string_value) return 0;
404                            if (DBFWriteStringAttribute(handle, record, field, PyString_AsString(string_value)))
405                            {
406                                    Py_DECREF(string_value);
407                                    return 1;
408                            }
409                            Py_DECREF(string_value);
410                            break;
411    
412                    case FTInteger:
413                            int_value = PyInt_AsLong(value);
414                            if (int_value == -1 && PyErr_Occurred()) return 0;
415                            if (DBFWriteIntegerAttribute(handle, record, field, int_value)) return 1;
416                            break;
417    
418                    case FTDouble:
419                            double_value = PyFloat_AsDouble(value);
420                            if (double_value == -1 && PyErr_Occurred()) return 0;
421                            if (DBFWriteDoubleAttribute(handle, record, field, double_value)) return 1;
422                            break;
423                            
424                    case FTLogical:
425                            logical_value = PyObject_IsTrue(value);
426                            if (logical_value == -1) return 0;
427                            if (DBFWriteLogicalAttribute(handle, record, field, logical_value ? 'T' : 'F')) return 1;
428                            break;
429    
430                    default:
431                            PyErr_Format(PyExc_TypeError, "Invalid field data type %d", type);
432                            return 0;
433                    }
434            }
435    
436            PyErr_Format(PyExc_IOError,     "can't write field %d of record %d", field, record);
437            return 0;
438    }
439    
440    
 /* The first argument to the DBFFile methods is a DBFFile pointer.  
  * We have to check whether handle is not NULL in most methods but not  
  * all. In the destructor and the close method, it's OK for handle to be  
  * NULL. We achieve this by checking whether the preprocessor macro  
  * NOCHECK_$name is defined. SWIG replaces $name with the name of the  
  * function for which the code is inserted. In the %{,%}-block below we  
  * define the macros for the destructor and the close() method.  
  */  
441    
442  %typemap(python,check) DBFFile *{  static PyObject* dbffile_write_attribute(DBFFileObject* self, PyObject* args)
443  %#ifndef NOCHECK_$name  {
444      if (!$target || !$target->handle)          int record, field;
445          SWIG_exception(SWIG_TypeError, "dbffile already closed");          PyObject* value;
446  %#endif          int type;
447    
448            if (!PyArg_ParseTuple(args, "iiO:write_attribute", &record, &field, &value)) return NULL;
449            
450            if (field < 0 || field >= DBFGetFieldCount(self->handle))
451            {
452                    PyErr_Format(PyExc_ValueError,
453                                    "field index %d out of bounds (field count: %d)",
454                                    field, DBFGetFieldCount(self->handle));
455                    return NULL;
456            }
457    
458            type = DBFGetFieldInfo(self->handle, field, NULL, NULL, NULL);
459            if (!do_write_attribute(self->handle, record, field, type, value)) return NULL;
460            Py_RETURN_NONE;
461  }  }
462    
 %{  
 #define NOCHECK_delete_DBFFile  
 #define NOCHECK_DBFFile_close  
 %}  
463    
464    
465  /* An exception handle for the constructor and the module level open()  static PyObject* dbffile_write_record(DBFFileObject* self, PyObject* args)
466   * and create() functions.  {
467   *          int record;
468   * Annoyingly, we *have* to put braces around the SWIG_exception()          PyObject* record_object;
469   * calls, at least in the python case, because of the way the macro is          int i, num_fields;
470   * written. Of course, always putting braces around the branches of an          
471   * if-statement is often considered good practice.          int type;
472   */          char name[12];
473  %typemap(python,except) DBFFile * {          PyObject* value = NULL;
474      $function;          
475      if (!$source)          if (!PyArg_ParseTuple(args, "iO:write_record", &record, &record_object)) return NULL;
476      {          
477          SWIG_exception(SWIG_MemoryError, "no memory");          num_fields = DBFGetFieldCount(self->handle);
478      }          
479      else if (!$source->handle)          /* mimic ShapeFile functionality where id = -1 means appending */
480      {          if (record == -1)
481          SWIG_exception(SWIG_IOError, "$name failed");          {
482      }                  record = num_fields;
483  }          }
484    
485  /* Exception handler for the add_field method */          if (PySequence_Check(record_object))
486  %typemap(python,except) int DBFFile_add_field {          {
487      $function;                  /* It's a sequence object. Iterate through all items in the
488      if ($source < 0)                  * sequence and write them to the appropriate field.
489      {                  */
490          SWIG_exception(SWIG_RuntimeError, "add_field failed");                  if (PySequence_Length(record_object) != num_fields)
491      }                  {
492  }                          PyErr_SetString(PyExc_TypeError, "record must have one item for each field");
493                            return NULL;
494  /* define and use some typemaps for the field_info() method whose                  }
495   * C-implementation has three output parameters that are returned                  for (i = 0; i < num_fields; ++i)
496   * through pointers passed into the function. SWIG already has                  {
497   * definitions for common types such as int* and we can use those for                          type = DBFGetFieldInfo(self->handle, i, NULL, NULL, NULL);
498   * the last two parameters:                          value = PySequence_GetItem(record_object, i);
499   */                          if (!value) return NULL;
500                            if (!do_write_attribute(self->handle, record, i, type, value))
501                            {
502                                    Py_DECREF(value);
503                                    return NULL;
504                            }
505                            Py_DECREF(value);
506                    }
507            }
508            else
509            {
510                    /* It's a dictionary-like object. Iterate over the names of the
511                    * known fields and write the corresponding item
512                    */
513                    for (i = 0; i < num_fields; ++i)
514                    {
515                            name[0] = '\0';
516                            type = DBFGetFieldInfo(self->handle, i, name, NULL, NULL);
517                            value = PyDict_GetItemString(record_object, name);
518                            if (value && !do_write_attribute(self->handle, record, i, type, value)) return NULL;
519                    }
520            }
521            
522            return PyInt_FromLong((long)record);
523    }
524    
 %apply int * OUTPUT { int * output_width }  
 %apply int * OUTPUT { int * output_decimals }  
525    
526  /* the fieldname has to be defined manually: */  
527  %typemap(python,ignore) char *fieldname_out(char temp[12]) {  static PyObject* dbffile_repr(DBFFileObject* self)
528      $target = temp;  {
529            /* TODO: it would be nice to do something like "dbflib.DBFFile(filename, mode)" instead */
530            return PyString_FromFormat("<dbflib.DBFFile object at %p>", self->handle);
531  }  }
532    
533  %typemap(python,argout) char *fieldname_out() {  
534      PyObject * string = PyString_FromString($source);  
535      $target = t_output_helper($target,string);  /* The commit method implementation
536    *
537    * The method relies on the DBFUpdateHeader method which is not
538    * available in shapelib <= 1.2.10.  setup.py defines
539    * HAVE_UPDATE_HEADER's value depending on whether the function is
540    * available in the shapelib version the code is compiled with.
541    */
542    #if HAVE_UPDATE_HEADER
543    static PyObject* dbffile_commit(DBFFileObject* self)
544    {
545            DBFUpdateHeader(self->handle);
546            Py_RETURN_NONE;
547  }  }
548    #endif
549    
550    
551    #if HAVE_LANGUAGE_DRIVER
552    
553  /*  static PyObject* dbffile_language_driver(DBFFileObject* self, void* closure)
554   * The SWIG-version of the DBFFile struct  {
555   */          return PyInt_FromLong((long)self->handle->nLanguageDriver);
556    }
557    
558    #endif
559    
560  typedef struct  
561    static struct PyMethodDef dbffile_methods[] =
562  {  {
563      %addmethods {          {"close", (PyCFunction)dbffile_close, METH_NOARGS,
564          DBFFile(const char *file, const char * mode = "rb") {                  "close() -> None\n\n"
565              DBFFile * self = malloc(sizeof(DBFFile));                  "closes DBFFile"},
566              if (self)          {"field_count", (PyCFunction)dbffile_field_count, METH_NOARGS,
567                  self->handle = DBFOpen(file, mode);                  "field_count() -> integer\n\n"
568              return self;                  "returns number of fields currently defined"},
569          }          {"record_count", (PyCFunction)dbffile_record_count, METH_NOARGS,
570                                "record_count() -> integer\n\n"
571          ~DBFFile() {                  "returns number of records that currently exist"},
572              if (self->handle)          {"field_info", (PyCFunction)dbffile_field_info, METH_VARARGS,
573                  DBFClose(self->handle);                  "field_info(field_index) -> (type, name, width, decimals)\n\n"
574              free(self);                  "returns info of a field as a tuple with:\n"
575          }                  "- type: the type of the field corresponding to the integer value of one "
576                    " of the constants FTString, FTInteger, ...\n"
577                    "- name: the name of the field as a string\n"
578                    "- width: the width of the field as a number of characters\n"
579                    "- decimals: the number of decimal digits" },
580            {"add_field", (PyCFunction)dbffile_add_field, METH_VARARGS,
581                    "add_field(type, name, width, decimals) -> field_index\n\n"
582                    "adds a new field and returns field index if successful\n"
583                    "- type: the type of the field corresponding to the integer value of one "
584                    " of the constants FTString, FTInteger, ...\n"
585                    "- name: the name of the field as a string\n"
586                    "- width: the width of the field as a number of characters\n"
587                    "- decimals: the number of decimal digits" },
588            {"read_attribute", (PyCFunction)dbffile_read_attribute, METH_VARARGS,
589                    "read_attribute(record_index, field_index) -> value\n\n"
590                    "returns the value of one field of a record"},
591            {"read_record", (PyCFunction)dbffile_read_record, METH_VARARGS,
592                    "read_record(record_index) -> dict\n\n"
593                    "returns an entire record as a dictionary of field names and values"},
594            {"write_attribute", (PyCFunction)dbffile_write_attribute, METH_VARARGS,
595                    "write_attribute(record_index, field_index, new_value)\n"
596                    "writes a single field of a record"},
597            {"write_record", (PyCFunction)dbffile_write_record, METH_VARARGS,
598                    "write_record(record_index, record) -> record_index\n\n"
599                    "Writes an entire record as a dict or a sequence, and return index of record\n"
600                    "Record can either be a dictionary in which case the keys are used as field names, "
601                    "or a sequence that must have an item for every field (length = field_count())"},
602    #if HAVE_UPDATE_HEADER
603            {"commit", (PyCFunction)dbffile_commit, METH_NOARGS,
604                    "commit() -> None"},
605    #endif
606            {NULL}
607    };
608    
         void close() {  
             if (self->handle)  
                 DBFClose(self->handle);  
             self->handle = NULL;  
         }  
609    
         int field_count() {  
             return DBFGetFieldCount(self->handle);  
         }  
610    
611          int record_count() {  static struct PyGetSetDef dbffile_getsetters[] =
612              return DBFGetRecordCount(self->handle);  {
613          }  #if HAVE_LANGUAGE_DRIVER
614            {"language_driver", (getter)dbffile_language_driver, NULL, "Language Driver ID (read-only)" },
615    #endif
616            {NULL}
617    };
618    
619    
620    
621    static PyTypeObject DBFFileType = PYSHAPELIB_DEFINE_TYPE(DBFFileObject, dbffile, "shapelib.DBFFile", 0);
622    
623    
624    
625    /* --- dbflib -------------------------------------------------------------------------------------------------------- */
626    
627    static PyObject* dbflib_open(PyObject* module, PyObject* args)
628    {
629            return PyObject_CallObject((PyObject*)&DBFFileType, args);
630    }
631    
632    
633          int field_info(int iField, char * fieldname_out,  
634                         int * output_width, int * output_decimals) {  static PyObject* dbflib_create(PyObject* module, PyObject* args)
635              return DBFGetFieldInfo(self->handle, iField, fieldname_out,  {
636                                     output_width, output_decimals);          char* file;
637            DBFFileObject* result;
638            DBFHandle handle = NULL;
639            int wideargument = 0;
640    
641    #if defined(SHPAPI_HAS_WIDE) && defined(Py_WIN_WIDE_FILENAMES)
642            if (GetVersion() < 0x80000000) {    /* On NT, so wide API available */
643                    PyObject *wfile;
644                    if (PyArg_ParseTuple(args, "U:create", &wfile))
645                    {
646                            wideargument = 1;
647                            handle = DBFCreateW(PyUnicode_AS_UNICODE(wfile));
648                            if (!handle)
649                            {
650                                    PyErr_SetFromErrnoWithFilenameObject(PyExc_IOError, wfile);
651                                    return NULL;
652                            }
653                    }
654                    else
655                    {
656                            /* Drop the argument parsing error as narrow
657                               strings are also valid. */
658                            PyErr_Clear();
659                    }
660          }          }
661                #endif
662          PyObject * read_record(int record) {          
663              return DBFInfo_read_record(self->handle, record);          if (!handle)
664            {
665                    if (!PyArg_ParseTuple(args, "et:create", Py_FileSystemDefaultEncoding, &file)) return NULL;
666                    handle = DBFCreate(file);
667                    if (!handle)
668                    {
669                                    PyErr_SetFromErrnoWithFilename(PyExc_IOError, file);
670                                    PyMem_Free(file);
671                                    return NULL;
672                    }
673                    PyMem_Free(file);
674          }          }
675    
676          PyObject * read_attribute(int record, int field) {          result = PyObject_New(DBFFileObject, &DBFFileType);
677              return DBFInfo_read_attribute(self->handle, record, field);          if (!result)
678            {
679                    DBFClose(handle);
680                    return PyErr_NoMemory();
681          }          }
682            
683            result->handle = handle;
684            return (PyObject*) result;
685    }
686    
687    
         int add_field(const char * pszFieldName, DBFFieldType eType,  
                       int nWidth, int nDecimals) {  
             return DBFAddField(self->handle, pszFieldName, eType, nWidth,  
                                nDecimals);  
         }  
688    
689          PyObject *write_record(int record, PyObject *dict_or_sequence) {  #if HAVE_LANGUAGE_DRIVER
690              return DBFInfo_write_record(self->handle, record,  
691                                          dict_or_sequence);  /** translate a numeric Language Driver ID to the name of Python's codec.
692     */
693    static PyObject* dbflib_language_driver_codec(PyObject* module, PyObject* args)
694    {
695            int ldid;
696            if (!PyArg_ParseTuple(args, "i:language_driver_name", &ldid)) return NULL;
697            if (ldid < 0 || ldid >= PYSHAPELIB_NUM_LANGUAGE_DRIVERS || !codecs[ldid])
698            {
699                    PyErr_SetString(PyExc_ValueError, "invalid driver id");
700                    return NULL;
701          }          }
702            return PyString_FromString(codecs[ldid]);
703    }
704    
705          int commit() {  /** translate a numeric Language Driver ID to a string represting its constant.
706              return DBFCommit(self->handle);   */
707    static PyObject* dbflib_language_driver_name(PyObject* module, PyObject* args)
708    {
709            int ldid;
710            if (!PyArg_ParseTuple(args, "i:language_driver_name", &ldid)) return NULL;
711            if (ldid < 0 || ldid >= PYSHAPELIB_NUM_LANGUAGE_DRIVERS || !drivers[ldid])
712            {
713                    PyErr_SetString(PyExc_ValueError, "invalid driver id");
714                    return NULL;
715          }          }
716            return PyString_FromString(drivers[ldid]);
717    }
718    
719      }  #endif
 } DBFFile;  
720    
721    
 /*  
  * Two module level functions, open() and create() that correspond to  
  * DBFOpen and DBFCreate respectively. open() is equivalent to the  
  * DBFFile constructor.  
  */  
722    
723    static struct PyMethodDef dbflib_methods[] =
724    {
725            {"open", (PyCFunction)dbflib_open, METH_VARARGS,
726                    "open(name [, mode]) -> DBFFile\n\n"
727                    "opens a DBFFile" },
728            {"create", (PyCFunction)dbflib_create, METH_VARARGS,
729                    "create(name [, language_driver]) -> DBFFile\n\n"
730                    "create a DBFFile " },
731    #if HAVE_LANGUAGE_DRIVER
732            {"language_driver_codec", (PyCFunction)dbflib_language_driver_codec, METH_VARARGS,
733                    "language_driver_codec(driver_id) -> string\n\n"
734                    "translate language driver id into the name of the Python's codec used as code page." },
735            {"language_driver_name", (PyCFunction)dbflib_language_driver_name, METH_VARARGS,
736                    "language_driver_name(driver_id) -> string\n\n"
737                    "translate language driver id into a string." },
738    #endif
739            {NULL}
740    };
741    
 %{  
     DBFFile * open_DBFFile(const char * file, const char * mode)  
     {  
         DBFFile * self = malloc(sizeof(DBFFile));  
         if (self)  
             self->handle = DBFOpen(file, mode);  
         return self;  
     }  
 %}  
   
 %name(open) %new DBFFile * open_DBFFile(const char * file,  
                                         const char * mode = "rb");  
   
 %{  
     DBFFile * create_DBFFile(const char * file)  
     {  
         DBFFile * self = malloc(sizeof(DBFFile));  
         if (self)  
             self->handle = DBFCreate(file);  
         return self;  
     }  
 %}  
 %name(create) %new DBFFile * create_DBFFile(const char * file);  
742    
743    PyMODINIT_FUNC initdbflib(void)
744    {
745            int i;
746    
747            PyObject* module = Py_InitModule("dbflib", dbflib_methods);
748            if (!module) return;
749            
750            PYSHAPELIB_ADD_TYPE(DBFFileType, "DBFFile");
751            
752            PYSHAPELIB_ADD_CONSTANT(FTString);
753            PYSHAPELIB_ADD_CONSTANT(FTInteger);
754            PYSHAPELIB_ADD_CONSTANT(FTDouble);
755            PYSHAPELIB_ADD_CONSTANT(FTLogical);
756            PYSHAPELIB_ADD_CONSTANT(FTInvalid);
757            PyModule_AddIntConstant(module, "_have_commit", HAVE_UPDATE_HEADER);
758    
759    #if HAVE_LANGUAGE_DRIVER
760            /* table compiled from these resources:
761             * http://www.clicketyclick.dk/databases/xbase/format/dbf.html
762             * http://www.esrinl.com/content/file.asp?id=307
763             * http://msdn2.microsoft.com/en-us/library/aa975345(VS.71).aspx
764             */
765            for (i = 0; i < PYSHAPELIB_NUM_LANGUAGE_DRIVERS; ++i)
766            {
767                    codecs[i] = NULL;
768                    drivers[i] = NULL;
769            }
770            PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x00, "cp1252", "NOT_SET");
771            PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x01, "cp437", "DOS_USA");
772            PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x02, "cp850", "DOS_INTERNATIONAL");
773            PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x03, "cp1252", "WINDOWS_ANSI");
774            PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x04, "mac_roman", "STANDARD_MACINTOSH");
775            PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x08, "cp865", "DANISH_OEM");
776            PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x09, "cp437", "DUTCH_OEM");
777            PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x0a, "cp850", "DUTCH_OEM_2");
778            PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x0b, "cp437", "FINNISH_OEM");
779            PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x0d, "cp437", "FRENCH_OEM");
780            PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x0e, "cp850", "FRENCH_OEM_2");
781            PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x0f, "cp437", "GERMAN_OEM");
782            PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x10, "cp850", "GERMAN_OEM_2");
783            PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x11, "cp437", "ITALIAN_OEM");
784            PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x12, "cp850", "ITALIAN_OEM_2");
785            PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x13, "cp932", "JAPANESE_SHIFT_JIS");
786            PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x14, "cp850", "SPANISH_OEM_2");
787            PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x15, "cp437", "SWEDISH_OEM");
788            PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x16, "cp850", "SWEDISH_OEM_2");
789            PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x17, "cp865", "NORWEGIAN_OEM");
790            PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x18, "cp437", "SPANISH_OEM");
791            PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x19, "cp437", "ENGLISH_BRITAIN_OEM");
792            PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x1a, "cp850", "ENGLISH_BRITAIN_OEM_2");
793            PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x0b, "cp437", "ENGLISH_US_OEM");
794            PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x1c, "cp863", "FRENCH_CANADA_OEM");
795            PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x1d, "cp850", "FRENCH_OEM_2");
796            PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x1f, "cp852", "CZECH_OEM");
797            PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x22, "cp852", "HUNGARIAN_OEM");
798            PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x23, "cp852", "POLISH_OEM");
799            PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x24, "cp860", "PORTUGUESE_OEM");
800            PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x25, "cp850", "PORTUGUESE_OEM_2");
801            PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x26, "cp866", "RUSSIAN_OEM");
802            PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x37, "cp850", "ENGLISH_US_OEM_2");
803            PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x40, "cp852", "ROMANIAN_OEM");
804            PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x4d, "cp936", "CHINESE_GBK_PRC");
805            PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x4e, "cp949", "KOREAN_ANSI_OEM);");
806            PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x4f, "cp950", "CHINESE_BIG5_TAIWAN");
807            PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x50, "cp874", "THAI_ANSI_OEM");
808            PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x57, "cp1252", "ESRI_ANSI");
809            PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x58, "cp1252", "WESTERN_EUROPEAN_ANSI");
810            PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x59, "cp1252", "SPANISH_ANSI");
811            PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x64, "cp852", "EASTERN_EUROPEAN_MSDOS");
812            PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x65, "cp866", "RUSSIAN_MSDOS");
813            PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x66, "cp865", "NORDIC_MSDOS");
814            PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x67, "cp861", "ICELANDIC_MSDOS");
815            PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x68, "cp895", "CZECH_MSDOS");
816            PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x69, "cp620", "POLISH_MSDOS");
817            PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x6a, "cp737", "GREEK_MSDOS");
818            PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x6b, "cp857", "TURKISH_MSDOS");
819            PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x6c, "cp863", "FRENCH_CANADA_MSDOS");
820            PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x78, "cp950", "TAIWAN_BIG5");
821            PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x79, "cp949", "HANGUL_WANSUG");
822            PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x7a, "cp936", "PRC_GBK");
823            PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x7b, "cp932", "JAPANESE_SHIFT_JIS");
824            PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x7c, "cp874", "THAI_WINDOWS_MSDOS");
825            PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x7d, "cp1255", "HEBREW_WINDOWS");
826            PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x7e, "cp1256", "ARABIC_WINDOWS");
827            PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x86, "cp737", "GREEK_OEM");
828            PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x87, "cp852", "SLOVENIAN_OEM");
829            PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x88, "cp857", "TURKISH_OEM");
830            PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x96, "mac_cyrillic", "RUSSIAN_MACINTOSH");
831            PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x97, "mac_latin2", "EASTERN_EUROPEAN_MACINTOSH");
832            PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x98, "mac_greek", "GREEK_MACINTOSH");
833            PYSHAPELIB_ADD_LANGUAGE_DRIVER(0xc8, "cp1250", "EASTERN_EUROPEAN_WINDOWS");
834            PYSHAPELIB_ADD_LANGUAGE_DRIVER(0xc9, "cp1251", "RUSSIAN_WINDOWS");
835            PYSHAPELIB_ADD_LANGUAGE_DRIVER(0xca, "cp1254", "TURKISH_WINDOWS");
836            PYSHAPELIB_ADD_LANGUAGE_DRIVER(0xcb, "cp1253", "GREEK_WINDOWS");
837            PYSHAPELIB_ADD_LANGUAGE_DRIVER(0xcc, "cp1257", "BALTIC_WINDOWS");
838    #endif
839    
840  /* constant definitions copied from shapefil.h */  }
 typedef enum {  
   FTString,  
   FTInteger,  
   FTDouble,  
   FTInvalid  
 } DBFFieldType;  

Legend:
Removed from v.1917  
changed lines
  Added in v.2753

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26