/[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

branches/WIP-pyshapelib-bramz/libraries/pyshapelib/dbflib.i revision 2734 by bramz, Thu Mar 1 12:42:59 2007 UTC branches/WIP-pyshapelib-bramz/libraries/pyshapelib/dbflibmodule.c revision 2752 by bramz, Tue Apr 10 23:45:00 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 ------------------------------------------------------------------------------------------------------- */
 DBFInfo_read_attribute(DBFInfo * handle, int record, int field)  
 {  
     if (record < 0 || record >= DBFGetRecordCount(handle))  
     {  
         PyErr_Format(PyExc_ValueError,  
                      "record index %d out of bounds (record count: %d)",  
                      record, DBFGetRecordCount(handle));  
         return NULL;  
     }  
92    
93      if (field < 0 || field >= DBFGetFieldCount(handle))  typedef struct {
94      {          PyObject_HEAD
95          PyErr_Format(PyExc_ValueError,          DBFHandle handle;
96                       "field index %d out of bounds (field count: %d)",  } DBFFileObject;
                      field, DBFGetFieldCount(handle));  
         return NULL;  
     }  
97    
     return do_read_attribute(handle, record, field, NULL);  
 }  
       
98    
 /* 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.  
  */  
99    
100  static PyObject *  /* allocator
101  DBFInfo_read_record(DBFInfo * handle, int record)  */
102    static PyObject* dbffile_new(PyTypeObject* type, PyObject* args, PyObject* kwds)
103  {  {
104      int num_fields;          DBFFileObject* self;    
105      int i;          self = (DBFFileObject*) type->tp_alloc(type, 0);
106      int type, width;          self->handle = NULL;
107      char name[12];          return (PyObject*) self;
     PyObject *dict;  
     PyObject *value;  
   
     if (record < 0 || record >= DBFGetRecordCount(handle))  
     {  
         PyErr_Format(PyExc_ValueError,  
                      "record index %d out of bounds (record count: %d)",  
                      record, DBFGetRecordCount(handle));  
         return NULL;  
     }  
   
     dict = PyDict_New();  
     if (!dict)  
         return NULL;  
           
     num_fields = DBFGetFieldCount(handle);  
     for (i = 0; i < num_fields; i++)  
     {  
         value = do_read_attribute(handle, record, i, name);  
         if (!value)  
             goto fail;  
   
         PyDict_SetItemString(dict, name, value);  
         Py_DECREF(value);  
     }  
   
     return dict;  
   
  fail:  
     Py_XDECREF(dict);  
     return NULL;  
108  }  }
109    
 /* 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.  
  */  
   
110    
 /* write a single field of a record. */  
 static int  
 write_field(DBFHandle handle, int record, int field, int type,  
             PyObject * value)  
 {  
     char * string_value;  
     int int_value;  
     double double_value;  
   
     if (value == Py_None)  
     {  
         if (!DBFWriteNULLAttribute(handle, record, field))  
         {  
             PyErr_Format(PyExc_IOError,  
                          "can't write NULL field %d of record %d",  
                          field, record);  
             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)  
         {  
             PyErr_SetString(PyExc_TypeError,  
                             "record must have one item for each field");  
             goto fail;  
         }  
         for (i = 0; i < length; i++)  
         {  
             type = DBFGetFieldInfo(handle, i, name, &width, NULL);  
             value = PySequence_GetItem(record_object, i);  
             if (value)  
             {  
                 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  
          */  
         for (i = 0; i < num_fields; i++)  
         {  
             type = DBFGetFieldInfo(handle, i, name, &width, NULL);  
111    
112              /* if the dictionary has the key name write that object to  /* deallocator
113               * the appropriate field, other wise just clear the python  */
114               * exception and do nothing.  static void dbffile_dealloc(DBFFileObject* self)
115               */  {
116              value = PyMapping_GetItemString(record_object, name);          DBFClose(self->handle);
117              if (value)          self->handle = NULL;
118              {          self->ob_type->tp_free((PyObject*)self);
                 if (!write_field(handle, record, i, type, value))  
                     goto fail;  
                 Py_DECREF(value);  
             }  
             else  
             {  
                 PyErr_Clear();  
             }  
         }  
     }  
   
     Py_INCREF(Py_None);  
     return Py_None;  
   
  fail:  
     Py_XDECREF(value);  
     return NULL;  
119  }  }
 %}  
120    
121    
122  /* The commit method implementation  
123   *  /* constructor
124   * The method relies on the DBFUpdateHeader method which is not  */
125   * available in shapelib <= 1.2.10.  setup.py defines  static int dbffile_init(DBFFileObject* self, PyObject* args, PyObject* kwds)
  * HAVE_UPDATE_HEADER's value depending on whether the function is  
  * available in the shapelib version the code is compiled with.  
  */  
 %{  
 static  
 void  
 DBFInfo_commit(DBFHandle handle)  
126  {  {
127  #if HAVE_UPDATE_HEADER          char* file = NULL;
128      DBFUpdateHeader(handle);          char* mode = "rb";
129            static char *kwlist[] = {"name", "mode", NULL};
130    
131            DBFClose(self->handle);
132            self->handle = NULL;
133    
134    #if defined(SHPAPI_HAS_WIDE) && defined(Py_WIN_WIDE_FILENAMES)
135            if (GetVersion() < 0x80000000) {    /* On NT, so wide API available */
136                    PyObject *wfile;
137                    if (PyArg_ParseTupleAndKeywords(args, kwds, "U|s:DBFFile", kwlist, &wfile, &mode))
138                    {
139                            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  #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   * The SWIG Interface definition.                  {
166   */                          PyErr_SetFromErrnoWithFilename(PyExc_IOError, file);
167                            PyMem_Free(file);
168                            return -1;
169                    }
170    
171  /* include some common SWIG type definitions and standard exception                  PyMem_Free(file);
172     handling code */          }
 %include typemaps.i  
 %include exception.i  
   
 /* As for ShapeFile in shapelib.i, We define a new C-struct that holds  
  * the DBFHandle. This is mainly done so we can separate the close()  
  * 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.  
  */  
173    
174  %{          return 0;
175      typedef struct {  }
         DBFHandle handle;  
     } DBFFile;  
 %}  
176    
177    
 /* 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.  
  */  
178    
179  %typemap(python,check) DBFFile *{  static PyObject* dbffile_close(DBFFileObject* self)
180  %#ifndef NOCHECK_$name  {
181      if (!$target || !$target->handle)          DBFClose(self->handle);
182          SWIG_exception(SWIG_TypeError, "dbffile already closed");          self->handle = NULL;
183  %#endif          Py_RETURN_NONE;
184  }  }
185    
 %{  
 #define NOCHECK_delete_DBFFile  
 #define NOCHECK_DBFFile_close  
 %}  
186    
187    
188  /* An exception handle for the constructor and the module level open()  static PyObject* dbffile_field_count(DBFFileObject* self)
189   * and create() functions.  {
190   *          return PyInt_FromLong((long)DBFGetFieldCount(self->handle));
191   * Annoyingly, we *have* to put braces around the SWIG_exception()  }
  * calls, at least in the python case, because of the way the macro is  
  * written. Of course, always putting braces around the branches of an  
  * if-statement is often considered good practice.  
  */  
 %typemap(python,except) DBFFile * {  
     $function;  
     if (!$source)  
     {  
         SWIG_exception(SWIG_MemoryError, "no memory");  
     }  
     else if (!$source->handle)  
     {  
         SWIG_exception(SWIG_IOError, "$name failed");  
     }  
 }  
   
 /* Exception handler for the add_field method */  
 %typemap(python,except) int DBFFile_add_field {  
     $function;  
     if ($source < 0)  
     {  
         SWIG_exception(SWIG_RuntimeError, "add_field failed");  
     }  
 }  
   
 /* define and use some typemaps for the field_info() method whose  
  * C-implementation has three output parameters that are returned  
  * through pointers passed into the function. SWIG already has  
  * definitions for common types such as int* and we can use those for  
  * the last two parameters:  
  */  
192    
 %apply int * OUTPUT { int * output_width }  
 %apply int * OUTPUT { int * output_decimals }  
193    
194  /* the fieldname has to be defined manually: */  
195  %typemap(python,ignore) char *fieldname_out(char temp[12]) {  static PyObject* dbffile_record_count(DBFFileObject* self)
196      $target = temp;  {
197            return PyInt_FromLong((long)DBFGetRecordCount(self->handle));
198  }  }
199    
200  %typemap(python,argout) char *fieldname_out() {  
201      PyObject * string = PyString_FromString($source);  
202      $target = t_output_helper($target,string);  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            
207            if (!PyArg_ParseTuple(args, "i:field_info", &field)) return NULL;
208            
209            field_name[0] = '\0';
210            field_type = DBFGetFieldInfo(self->handle, field, field_name, &width, &decimals);
211            
212            return Py_BuildValue("isii", field_type, field_name, width, decimals);
213  }  }
214    
215    
216    
217  /*  static PyObject* dbffile_add_field(DBFFileObject* self, PyObject* args)
218   * The SWIG-version of the DBFFile struct  {
219   */          char* name;
220            int type, width, decimals;
221            int field;
222            
223            if (!PyArg_ParseTuple(args, "siii:add_field", &name, &type, &width, &decimals)) return NULL;
224            
225            field = DBFAddField(self->handle, name, (DBFFieldType)type, width, decimals);
226            
227            if (field < 0)
228            {
229                    PyErr_SetString(PyExc_ValueError, "Failed to add field due to inappropriate field definition");
230                    return NULL;
231            }
232            return PyInt_FromLong((long)field);
233    }
234    
235    
236  typedef struct  
237    /* Read one attribute from the dbf handle and return it as a new python object
238    *
239    * If an error occurs, set the appropriate Python exception and return
240    * NULL.
241    *
242    * Assume that the values of the record and field arguments are valid.
243    * The name argument will be passed to DBFGetFieldInfo as is and should
244    * thus be either NULL or a pointer to an array of at least 12 chars
245    */
246    static PyObject* do_read_attribute(DBFHandle handle, int record, int field, char * name)
247  {  {
248      %addmethods {          int type, width;
249          DBFFile(const char *file, const char * mode = "rb") {          const char* string;
250              DBFFile * self = malloc(sizeof(DBFFile));          type = DBFGetFieldInfo(handle, field, name, &width, NULL);
251              if (self)          
252                  self->handle = DBFOpen(file, mode);          /* For strings NULL and the empty string are indistinguishable
253              return self;          * in DBF files. We prefer empty strings instead for backwards
254            * compatibility reasons because older wrapper versions returned
255            * emtpy strings as empty strings.
256            */
257            if (type != FTString && DBFIsAttributeNULL(handle, record, field))
258            {
259                    Py_RETURN_NONE;
260          }          }
261                        else
262          ~DBFFile() {          {
263              if (self->handle)                  switch (type)
264                  DBFClose(self->handle);                  {
265              free(self);                  case FTString:
266                            string = DBFReadStringAttribute(handle, record, field);
267                            if (string) return decode_string(handle, string);
268    
269                    case FTInteger:
270                            return PyInt_FromLong((long)DBFReadIntegerAttribute(handle, record, field));
271    
272                    case FTDouble:
273                            return PyFloat_FromDouble(DBFReadDoubleAttribute(handle, record, field));
274                            
275                    case FTLogical:
276                            string = DBFReadLogicalAttribute(handle, record, field);
277                            if (string)
278                            {
279                                    switch (string[0])
280                                    {
281                                    case 'F':
282                                    case 'N':
283                                            Py_RETURN_FALSE;
284                                    case 'T':
285                                    case 'Y':
286                                            Py_RETURN_TRUE;
287                                    }
288                            }
289                            break;
290    
291                    default:
292                            PyErr_Format(PyExc_TypeError, "Invalid field data type %d", type);
293                            return NULL;
294                    }
295          }          }
296            
297            PyErr_Format(PyExc_IOError,     "Can't read value for row %d column %d", record, field);
298            return NULL;
299    }    
300    
301    
302    
303          void close() {  /* the read_attribute method. Return the value of the given record and
304              if (self->handle)  * field as a python object of the appropriate type.
305                  DBFClose(self->handle);  */
306              self->handle = NULL;  static PyObject* dbffile_read_attribute(DBFFileObject* self, PyObject* args)
307    {
308            int record, field;
309    
310            if (!PyArg_ParseTuple(args, "ii:read_field", &record, &field)) return NULL;
311            
312            if (record < 0 || record >= DBFGetRecordCount(self->handle))
313            {
314                    PyErr_Format(PyExc_ValueError,
315                                    "record index %d out of bounds (record count: %d)",
316                                    record, DBFGetRecordCount(self->handle));
317                    return NULL;
318          }          }
319    
320          int field_count() {          if (field < 0 || field >= DBFGetFieldCount(self->handle))
321              return DBFGetFieldCount(self->handle);          {
322                    PyErr_Format(PyExc_ValueError,
323                                    "field index %d out of bounds (field count: %d)",
324                                    field, DBFGetFieldCount(self->handle));
325                    return NULL;
326          }          }
327    
328          int record_count() {          return do_read_attribute(self->handle, record, field, NULL);
329              return DBFGetRecordCount(self->handle);  }
330    
331    
332    
333    /* the read_record method. Return the record record as a dictionary with
334    * whose keys are the names of the fields, and their values as the
335    * appropriate Python type.
336    */
337    static PyObject* dbffile_read_record(DBFFileObject* self, PyObject* args)
338    {
339            int record;
340            int num_fields;
341            int i;
342            char name[12];
343            PyObject *dict;
344            PyObject *value = NULL;
345    
346            if (!PyArg_ParseTuple(args, "i:read_record", &record)) return NULL;
347    
348            if (record < 0 || record >= DBFGetRecordCount(self->handle))
349            {
350                    PyErr_Format(PyExc_ValueError,
351                            "record index %d out of bounds (record count: %d)",
352                            record, DBFGetRecordCount(self->handle));
353                    return NULL;
354            }
355    
356            dict = PyDict_New();
357            if (!dict) return NULL;
358            
359            num_fields = DBFGetFieldCount(self->handle);
360            for (i = 0; i < num_fields; i++)
361            {
362                    value = do_read_attribute(self->handle, record, i, name);
363                    if (!value || PyDict_SetItemString(dict, name, value) < 0) goto fail;
364                    Py_DECREF(value);
365                    value = NULL;
366          }          }
367    
368          int field_info(int iField, char * fieldname_out,          return dict;
369                         int * output_width, int * output_decimals) {  
370              return DBFGetFieldInfo(self->handle, iField, fieldname_out,  fail:
371                                     output_width, output_decimals);          Py_XDECREF(value);
372            Py_DECREF(dict);
373            return NULL;
374    }
375    
376    
377    
378    /* write a single field of a record. */
379    static int do_write_field(DBFHandle handle, int record, int field, int type, PyObject* value)
380    {
381            PyObject* encoded_string = NULL;
382            char * string_value;
383            int int_value;
384            double double_value;
385            int logical_value;
386    
387            if (value == Py_None)
388            {
389                    if (DBFWriteNULLAttribute(handle, record, field)) return 1;
390          }          }
391                        else
392          PyObject * read_record(int record) {          {
393              return DBFInfo_read_record(self->handle, record);                  switch (type)
394                    {
395                    case FTString:
396                            encoded_string = encode_string(handle, value);
397                            if (!encoded_string) return 0;
398                            string_value = PyString_AsString(encoded_string);
399                            if (!string_value)
400                            {
401                                    Py_DECREF(encoded_string);
402                                    return 0;
403                            }
404                            if (DBFWriteStringAttribute(handle, record, field, string_value))
405                            {
406                                    Py_DECREF(encoded_string);
407                                    return 1;
408                            }
409                            Py_DECREF(encoded_string);
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          PyObject * read_attribute(int record, int field) {          PyErr_Format(PyExc_IOError,     "can't write field %d of record %d", field, record);
437              return DBFInfo_read_attribute(self->handle, record, field);          return 0;
438    }
439    
440    
441    
442    static PyObject* dbffile_write_field(DBFFileObject* self, PyObject* args)
443    {
444            int record, field;
445            PyObject* value;
446            int type;
447    
448            if (!PyArg_ParseTuple(args, "iiO:write_field", &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          int add_field(const char * pszFieldName, DBFFieldType eType,          type = DBFGetFieldInfo(self->handle, field, NULL, NULL, NULL);
459                        int nWidth, int nDecimals) {          if (!do_write_field(self->handle, record, field, type, value)) return NULL;
460              return DBFAddField(self->handle, pszFieldName, eType, nWidth,          Py_RETURN_NONE;
461                                 nDecimals);  }
462    
463    
464    
465    static PyObject* dbffile_write_record(DBFFileObject* self, PyObject* args)
466    {
467            int record;
468            PyObject* record_object;
469            int i, num_fields;
470            
471            int type;
472            char name[12];
473            PyObject* value = NULL;
474            
475            if (!PyArg_ParseTuple(args, "iO:write_record", &record, &record_object)) return NULL;
476            
477            num_fields = DBFGetFieldCount(self->handle);
478            
479            /* mimic ShapeFile functionality where id = -1 means appending */
480            if (record == -1)
481            {
482                    record = num_fields;
483          }          }
484    
485          PyObject *write_record(int record, PyObject *dict_or_sequence) {          if (PySequence_Check(record_object))
486              return DBFInfo_write_record(self->handle, record,          {
487                                          dict_or_sequence);                  /* It's a sequence object. Iterate through all items in the
488                    * sequence and write them to the appropriate field.
489                    */
490                    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                    }
495                    for (i = 0; i < num_fields; ++i)
496                    {
497                            type = DBFGetFieldInfo(self->handle, i, NULL, NULL, NULL);
498                            value = PySequence_GetItem(record_object, i);
499                            if (!value) return NULL;
500                            if (!do_write_field(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_field(self->handle, record, i, type, value)) return NULL;
519                    }
520            }
521            
522            return PyInt_FromLong((long)record);
523    }
524    
525    
526    
527    static PyObject* dbffile_repr(DBFFileObject* self)
528    {
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    
534    
535    /* 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    {
555            return PyInt_FromLong((long)self->handle->nLanguageDriver);
556    }
557    
558    #endif
559    
560    
561    static struct PyMethodDef dbffile_methods[] =
562    {
563            {"close", (PyCFunction)dbffile_close, METH_NOARGS,
564                    "close() -> None\n\n"
565                    "closes DBFFile"},
566            {"field_count", (PyCFunction)dbffile_field_count, METH_NOARGS,
567                    "field_count() -> integer\n\n"
568                    "returns number of fields currently defined"},
569            {"record_count", (PyCFunction)dbffile_record_count, METH_NOARGS,
570                    "record_count() -> integer\n\n"
571                    "returns number of records that currently exist"},
572            {"field_info", (PyCFunction)dbffile_field_info, METH_VARARGS,
573                    "field_info(field_index) -> (type, name, width, decimals)\n\n"
574                    "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_field", (PyCFunction)dbffile_write_field, METH_VARARGS,
595                    "write_field(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    
609    
610    
611    static struct PyGetSetDef dbffile_getsetters[] =
612    {
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    
634    static PyObject* dbflib_create(PyObject* module, PyObject* args)
635    {
636            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            
663            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          void commit() {          result = PyObject_New(DBFFileObject, &DBFFileType);
677              DBFInfo_commit(self->handle);          if (!result)
678            {
679                    DBFClose(handle);
680                    return PyErr_NoMemory();
681          }          }
682          /* Delete the commit method from the class if it doesn't have a          
683           * real implementation.          result->handle = handle;
684           */          return (PyObject*) result;
685          %pragma(python) addtomethod="__class__:if not dbflibc._have_commit: del commit"  }
686    
         /* The __del__ method generated by the old SWIG version we're  
          * tries to access self.thisown which may not be set at all when  
          * there was an exception during construction.  Therefore we  
          * override it with our own version.  
          * FIXME: It would be better to upgrade to a newer SWIG version  
          * or to get rid of SWIG entirely.  
          */  
         %pragma(python) addtoclass = "  
     def __del__(self,dbflibc=dbflibc):  
         if getattr(self, 'thisown', 0):  
             dbflibc.delete_DBFFile(self)  
     "  
687    
688    
689      }  #if HAVE_LANGUAGE_DRIVER
 } DBFFile;  
690    
691    /** 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  /*  /** translate a numeric Language Driver ID to a string represting its constant.
  * Two module level functions, open() and create() that correspond to  
  * DBFOpen and DBFCreate respectively. open() is equivalent to the  
  * DBFFile constructor.  
706   */   */
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
720    
 %{  
     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);  
721    
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    
 /* constant definitions copied from shapefil.h */  
 typedef enum {  
   FTString,  
   FTInteger,  
   FTDouble,  
   FTInvalid  
 } DBFFieldType;  
   
   
 /* Put the value of the HAVE_UPDATE_HEADER preprocessor macro into the  
  * wrapper so that the __class__ pragma above knows when to remove the  
  * commit method  
  */  
 const int _have_commit = HAVE_UPDATE_HEADER;  
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    }

Legend:
Removed from v.2734  
changed lines
  Added in v.2752

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26